1 // statements.cc -- Go frontend statements.
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.
11 #ifndef ENABLE_BUILD_WITH_CXX
20 #include "tree-iterator.h"
21 #include "tree-flow.h"
24 #ifndef ENABLE_BUILD_WITH_CXX
30 #include "expressions.h"
32 #include "statements.h"
36 Statement::Statement(Statement_classification classification,
37 source_location location)
38 : classification_(classification), location_(location)
42 Statement::~Statement()
46 // Traverse the tree. The work of walking the components is handled
50 Statement::traverse(Block* block, size_t* pindex, Traverse* traverse)
52 if (this->classification_ == STATEMENT_ERROR)
53 return TRAVERSE_CONTINUE;
55 unsigned int traverse_mask = traverse->traverse_mask();
57 if ((traverse_mask & Traverse::traverse_statements) != 0)
59 int t = traverse->statement(block, pindex, this);
60 if (t == TRAVERSE_EXIT)
62 else if (t == TRAVERSE_SKIP_COMPONENTS)
63 return TRAVERSE_CONTINUE;
66 // No point in checking traverse_mask here--a statement may contain
67 // other blocks or statements, and if we got here we always want to
69 return this->do_traverse(traverse);
72 // Traverse the contents of a statement.
75 Statement::traverse_contents(Traverse* traverse)
77 return this->do_traverse(traverse);
80 // Traverse assignments.
83 Statement::traverse_assignments(Traverse_assignments* tassign)
85 if (this->classification_ == STATEMENT_ERROR)
87 return this->do_traverse_assignments(tassign);
90 // Traverse an expression in a statement. This is a helper function
94 Statement::traverse_expression(Traverse* traverse, Expression** expr)
96 if ((traverse->traverse_mask()
97 & (Traverse::traverse_types | Traverse::traverse_expressions)) == 0)
98 return TRAVERSE_CONTINUE;
99 return Expression::traverse(expr, traverse);
102 // Traverse an expression list in a statement. This is a helper
103 // function for child classes.
106 Statement::traverse_expression_list(Traverse* traverse,
107 Expression_list* expr_list)
109 if (expr_list == NULL)
110 return TRAVERSE_CONTINUE;
111 if ((traverse->traverse_mask() & Traverse::traverse_expressions) == 0)
112 return TRAVERSE_CONTINUE;
113 return expr_list->traverse(traverse);
116 // Traverse a type in a statement. This is a helper function for
120 Statement::traverse_type(Traverse* traverse, Type* type)
122 if ((traverse->traverse_mask()
123 & (Traverse::traverse_types | Traverse::traverse_expressions)) == 0)
124 return TRAVERSE_CONTINUE;
125 return Type::traverse(type, traverse);
128 // Set type information for unnamed constants. This is really done by
132 Statement::determine_types()
134 this->do_determine_types();
137 // If this is a thunk statement, return it.
140 Statement::thunk_statement()
142 Thunk_statement* ret = this->convert<Thunk_statement, STATEMENT_GO>();
144 ret = this->convert<Thunk_statement, STATEMENT_DEFER>();
148 // Get a tree for a Statement. This is really done by the child
152 Statement::get_tree(Translate_context* context)
154 if (this->classification_ == STATEMENT_ERROR)
155 return error_mark_node;
157 return this->do_get_tree(context);
160 // Build tree nodes and set locations.
163 Statement::build_stmt_1(int tree_code_value, tree node)
165 tree ret = build1(static_cast<tree_code>(tree_code_value),
166 void_type_node, node);
167 SET_EXPR_LOCATION(ret, this->location_);
171 // Note that this statement is erroneous. This is called by children
172 // when they discover an error.
175 Statement::set_is_error()
177 this->classification_ = STATEMENT_ERROR;
180 // For children to call to report an error conveniently.
183 Statement::report_error(const char* msg)
185 error_at(this->location_, "%s", msg);
186 this->set_is_error();
189 // An error statement, used to avoid crashing after we report an
192 class Error_statement : public Statement
195 Error_statement(source_location location)
196 : Statement(STATEMENT_ERROR, location)
201 do_traverse(Traverse*)
202 { return TRAVERSE_CONTINUE; }
205 do_get_tree(Translate_context*)
206 { gcc_unreachable(); }
209 // Make an error statement.
212 Statement::make_error_statement(source_location location)
214 return new Error_statement(location);
217 // Class Variable_declaration_statement.
219 Variable_declaration_statement::Variable_declaration_statement(
221 : Statement(STATEMENT_VARIABLE_DECLARATION, var->var_value()->location()),
226 // We don't actually traverse the variable here; it was traversed
227 // while traversing the Block.
230 Variable_declaration_statement::do_traverse(Traverse*)
232 return TRAVERSE_CONTINUE;
235 // Traverse the assignments in a variable declaration. Note that this
236 // traversal is different from the usual traversal.
239 Variable_declaration_statement::do_traverse_assignments(
240 Traverse_assignments* tassign)
242 tassign->initialize_variable(this->var_);
246 // Return the tree for a variable declaration.
249 Variable_declaration_statement::do_get_tree(Translate_context* context)
251 tree val = this->var_->get_tree(context->gogo(), context->function());
252 if (val == error_mark_node || TREE_TYPE(val) == error_mark_node)
253 return error_mark_node;
254 Variable* variable = this->var_->var_value();
256 tree init = variable->get_init_tree(context->gogo(), context->function());
257 if (init == error_mark_node)
258 return error_mark_node;
260 // If this variable lives on the heap, we need to allocate it now.
261 if (!variable->is_in_heap())
263 DECL_INITIAL(val) = init;
264 return this->build_stmt_1(DECL_EXPR, val);
268 gcc_assert(TREE_CODE(val) == INDIRECT_REF);
269 tree decl = TREE_OPERAND(val, 0);
270 gcc_assert(TREE_CODE(decl) == VAR_DECL);
271 tree type = TREE_TYPE(decl);
272 gcc_assert(POINTER_TYPE_P(type));
273 tree size = TYPE_SIZE_UNIT(TREE_TYPE(type));
274 tree space = context->gogo()->allocate_memory(variable->type(), size,
276 space = fold_convert(TREE_TYPE(decl), space);
277 DECL_INITIAL(decl) = space;
278 return build2(COMPOUND_EXPR, void_type_node,
279 this->build_stmt_1(DECL_EXPR, decl),
280 build2(MODIFY_EXPR, void_type_node, val, init));
284 // Make a variable declaration.
287 Statement::make_variable_declaration(Named_object* var)
289 return new Variable_declaration_statement(var);
292 // Class Temporary_statement.
294 // Return the type of the temporary variable.
297 Temporary_statement::type() const
299 return this->type_ != NULL ? this->type_ : this->init_->type();
302 // Return the tree for the temporary variable.
305 Temporary_statement::get_decl() const
307 if (this->decl_ == NULL)
309 gcc_assert(saw_errors());
310 return error_mark_node;
318 Temporary_statement::do_traverse(Traverse* traverse)
320 if (this->init_ == NULL)
321 return TRAVERSE_CONTINUE;
323 return this->traverse_expression(traverse, &this->init_);
326 // Traverse assignments.
329 Temporary_statement::do_traverse_assignments(Traverse_assignments* tassign)
331 if (this->init_ == NULL)
333 tassign->value(&this->init_, true, true);
340 Temporary_statement::do_determine_types()
342 if (this->init_ != NULL)
344 if (this->type_ == NULL)
345 this->init_->determine_type_no_context();
348 Type_context context(this->type_, false);
349 this->init_->determine_type(&context);
353 if (this->type_ == NULL)
354 this->type_ = this->init_->type();
356 if (this->type_->is_abstract())
357 this->type_ = this->type_->make_non_abstract_type();
363 Temporary_statement::do_check_types(Gogo*)
365 if (this->type_ != NULL && this->init_ != NULL)
368 if (!Type::are_assignable(this->type_, this->init_->type(), &reason))
371 error_at(this->location(), "incompatible types in assignment");
373 error_at(this->location(), "incompatible types in assignment (%s)",
375 this->set_is_error();
383 Temporary_statement::do_get_tree(Translate_context* context)
385 gcc_assert(this->decl_ == NULL_TREE);
386 tree type_tree = this->type()->get_tree(context->gogo());
387 if (type_tree == error_mark_node)
389 this->decl_ = error_mark_node;
390 return error_mark_node;
392 // We can only use create_tmp_var if the type is not addressable.
393 if (!TREE_ADDRESSABLE(type_tree))
395 this->decl_ = create_tmp_var(type_tree, "GOTMP");
396 DECL_SOURCE_LOCATION(this->decl_) = this->location();
400 gcc_assert(context->function() != NULL && context->block() != NULL);
401 tree decl = build_decl(this->location(), VAR_DECL,
402 create_tmp_var_name("GOTMP"),
404 DECL_ARTIFICIAL(decl) = 1;
405 DECL_IGNORED_P(decl) = 1;
407 gcc_assert(current_function_decl != NULL_TREE);
408 DECL_CONTEXT(decl) = current_function_decl;
410 // We have to add this variable to the block so that it winds up
412 tree block_tree = context->block_tree();
413 gcc_assert(block_tree != NULL_TREE);
414 DECL_CHAIN(decl) = BLOCK_VARS(block_tree);
415 BLOCK_VARS(block_tree) = decl;
419 if (this->init_ != NULL)
420 DECL_INITIAL(this->decl_) =
421 Expression::convert_for_assignment(context, this->type(),
423 this->init_->get_tree(context),
425 if (this->is_address_taken_)
426 TREE_ADDRESSABLE(this->decl_) = 1;
427 return this->build_stmt_1(DECL_EXPR, this->decl_);
430 // Make and initialize a temporary variable in BLOCK.
433 Statement::make_temporary(Type* type, Expression* init,
434 source_location location)
436 return new Temporary_statement(type, init, location);
439 // An assignment statement.
441 class Assignment_statement : public Statement
444 Assignment_statement(Expression* lhs, Expression* rhs,
445 source_location location)
446 : Statement(STATEMENT_ASSIGNMENT, location),
452 do_traverse(Traverse* traverse);
455 do_traverse_assignments(Traverse_assignments*);
458 do_determine_types();
461 do_check_types(Gogo*);
464 do_get_tree(Translate_context*);
467 // Left hand side--the lvalue.
469 // Right hand side--the rvalue.
476 Assignment_statement::do_traverse(Traverse* traverse)
478 if (this->traverse_expression(traverse, &this->lhs_) == TRAVERSE_EXIT)
479 return TRAVERSE_EXIT;
480 return this->traverse_expression(traverse, &this->rhs_);
484 Assignment_statement::do_traverse_assignments(Traverse_assignments* tassign)
486 tassign->assignment(&this->lhs_, &this->rhs_);
490 // Set types for the assignment.
493 Assignment_statement::do_determine_types()
495 this->lhs_->determine_type_no_context();
496 Type_context context(this->lhs_->type(), false);
497 this->rhs_->determine_type(&context);
500 // Check types for an assignment.
503 Assignment_statement::do_check_types(Gogo*)
505 // The left hand side must be either addressable, a map index
506 // expression, or the blank identifier.
507 if (!this->lhs_->is_addressable()
508 && this->lhs_->map_index_expression() == NULL
509 && !this->lhs_->is_sink_expression())
511 if (!this->lhs_->type()->is_error_type())
512 this->report_error(_("invalid left hand side of assignment"));
516 Type* lhs_type = this->lhs_->type();
517 Type* rhs_type = this->rhs_->type();
519 if (!Type::are_assignable(lhs_type, rhs_type, &reason))
522 error_at(this->location(), "incompatible types in assignment");
524 error_at(this->location(), "incompatible types in assignment (%s)",
526 this->set_is_error();
529 if (lhs_type->is_error_type()
530 || rhs_type->is_error_type()
531 || lhs_type->is_undefined()
532 || rhs_type->is_undefined())
534 // Make sure we get the error for an undefined type.
537 this->set_is_error();
541 // Build a tree for an assignment statement.
544 Assignment_statement::do_get_tree(Translate_context* context)
546 tree rhs_tree = this->rhs_->get_tree(context);
548 if (this->lhs_->is_sink_expression())
551 tree lhs_tree = this->lhs_->get_tree(context);
553 if (lhs_tree == error_mark_node || rhs_tree == error_mark_node)
554 return error_mark_node;
556 rhs_tree = Expression::convert_for_assignment(context, this->lhs_->type(),
557 this->rhs_->type(), rhs_tree,
559 if (rhs_tree == error_mark_node)
560 return error_mark_node;
562 return fold_build2_loc(this->location(), MODIFY_EXPR, void_type_node,
566 // Make an assignment statement.
569 Statement::make_assignment(Expression* lhs, Expression* rhs,
570 source_location location)
572 return new Assignment_statement(lhs, rhs, location);
575 // The Move_ordered_evals class is used to find any subexpressions of
576 // an expression that have an evaluation order dependency. It creates
577 // temporary variables to hold them.
579 class Move_ordered_evals : public Traverse
582 Move_ordered_evals(Block* block)
583 : Traverse(traverse_expressions),
589 expression(Expression**);
592 // The block where new temporary variables should be added.
597 Move_ordered_evals::expression(Expression** pexpr)
599 // We have to look at subexpressions first.
600 if ((*pexpr)->traverse_subexpressions(this) == TRAVERSE_EXIT)
601 return TRAVERSE_EXIT;
602 if ((*pexpr)->must_eval_in_order())
604 source_location loc = (*pexpr)->location();
605 Temporary_statement* temp = Statement::make_temporary(NULL, *pexpr, loc);
606 this->block_->add_statement(temp);
607 *pexpr = Expression::make_temporary_reference(temp, loc);
609 return TRAVERSE_SKIP_COMPONENTS;
612 // An assignment operation statement.
614 class Assignment_operation_statement : public Statement
617 Assignment_operation_statement(Operator op, Expression* lhs, Expression* rhs,
618 source_location location)
619 : Statement(STATEMENT_ASSIGNMENT_OPERATION, location),
620 op_(op), lhs_(lhs), rhs_(rhs)
625 do_traverse(Traverse*);
628 do_traverse_assignments(Traverse_assignments*)
629 { gcc_unreachable(); }
632 do_lower(Gogo*, Block*);
635 do_get_tree(Translate_context*)
636 { gcc_unreachable(); }
639 // The operator (OPERATOR_PLUSEQ, etc.).
650 Assignment_operation_statement::do_traverse(Traverse* traverse)
652 if (this->traverse_expression(traverse, &this->lhs_) == TRAVERSE_EXIT)
653 return TRAVERSE_EXIT;
654 return this->traverse_expression(traverse, &this->rhs_);
657 // Lower an assignment operation statement to a regular assignment
661 Assignment_operation_statement::do_lower(Gogo*, Block* enclosing)
663 source_location loc = this->location();
665 // We have to evaluate the left hand side expression only once. We
666 // do this by moving out any expression with side effects.
667 Block* b = new Block(enclosing, loc);
668 Move_ordered_evals moe(b);
669 this->lhs_->traverse_subexpressions(&moe);
671 Expression* lval = this->lhs_->copy();
676 case OPERATOR_PLUSEQ:
679 case OPERATOR_MINUSEQ:
688 case OPERATOR_MULTEQ:
697 case OPERATOR_LSHIFTEQ:
698 op = OPERATOR_LSHIFT;
700 case OPERATOR_RSHIFTEQ:
701 op = OPERATOR_RSHIFT;
706 case OPERATOR_BITCLEAREQ:
707 op = OPERATOR_BITCLEAR;
713 Expression* binop = Expression::make_binary(op, lval, this->rhs_, loc);
714 Statement* s = Statement::make_assignment(this->lhs_, binop, loc);
715 if (b->statements()->empty())
723 return Statement::make_block_statement(b, loc);
727 // Make an assignment operation statement.
730 Statement::make_assignment_operation(Operator op, Expression* lhs,
731 Expression* rhs, source_location location)
733 return new Assignment_operation_statement(op, lhs, rhs, location);
736 // A tuple assignment statement. This differs from an assignment
737 // statement in that the right-hand-side expressions are evaluated in
740 class Tuple_assignment_statement : public Statement
743 Tuple_assignment_statement(Expression_list* lhs, Expression_list* rhs,
744 source_location location)
745 : Statement(STATEMENT_TUPLE_ASSIGNMENT, location),
751 do_traverse(Traverse* traverse);
754 do_traverse_assignments(Traverse_assignments*)
755 { gcc_unreachable(); }
758 do_lower(Gogo*, Block*);
761 do_get_tree(Translate_context*)
762 { gcc_unreachable(); }
765 // Left hand side--a list of lvalues.
766 Expression_list* lhs_;
767 // Right hand side--a list of rvalues.
768 Expression_list* rhs_;
774 Tuple_assignment_statement::do_traverse(Traverse* traverse)
776 if (this->traverse_expression_list(traverse, this->lhs_) == TRAVERSE_EXIT)
777 return TRAVERSE_EXIT;
778 return this->traverse_expression_list(traverse, this->rhs_);
781 // Lower a tuple assignment. We use temporary variables to split it
782 // up into a set of single assignments.
785 Tuple_assignment_statement::do_lower(Gogo*, Block* enclosing)
787 source_location loc = this->location();
789 Block* b = new Block(enclosing, loc);
791 // First move out any subexpressions on the left hand side. The
792 // right hand side will be evaluated in the required order anyhow.
793 Move_ordered_evals moe(b);
794 for (Expression_list::const_iterator plhs = this->lhs_->begin();
795 plhs != this->lhs_->end();
797 (*plhs)->traverse_subexpressions(&moe);
799 std::vector<Temporary_statement*> temps;
800 temps.reserve(this->lhs_->size());
802 Expression_list::const_iterator prhs = this->rhs_->begin();
803 for (Expression_list::const_iterator plhs = this->lhs_->begin();
804 plhs != this->lhs_->end();
807 gcc_assert(prhs != this->rhs_->end());
809 if ((*plhs)->is_error_expression()
810 || (*plhs)->type()->is_error_type()
811 || (*prhs)->is_error_expression()
812 || (*prhs)->type()->is_error_type())
815 if ((*plhs)->is_sink_expression())
817 b->add_statement(Statement::make_statement(*prhs));
821 Temporary_statement* temp = Statement::make_temporary((*plhs)->type(),
823 b->add_statement(temp);
824 temps.push_back(temp);
827 gcc_assert(prhs == this->rhs_->end());
829 prhs = this->rhs_->begin();
830 std::vector<Temporary_statement*>::const_iterator ptemp = temps.begin();
831 for (Expression_list::const_iterator plhs = this->lhs_->begin();
832 plhs != this->lhs_->end();
835 if ((*plhs)->is_error_expression()
836 || (*plhs)->type()->is_error_type()
837 || (*prhs)->is_error_expression()
838 || (*prhs)->type()->is_error_type())
841 if ((*plhs)->is_sink_expression())
844 Expression* ref = Expression::make_temporary_reference(*ptemp, loc);
845 Statement* s = Statement::make_assignment(*plhs, ref, loc);
849 gcc_assert(ptemp == temps.end());
851 return Statement::make_block_statement(b, loc);
854 // Make a tuple assignment statement.
857 Statement::make_tuple_assignment(Expression_list* lhs, Expression_list* rhs,
858 source_location location)
860 return new Tuple_assignment_statement(lhs, rhs, location);
863 // A tuple assignment from a map index expression.
866 class Tuple_map_assignment_statement : public Statement
869 Tuple_map_assignment_statement(Expression* val, Expression* present,
870 Expression* map_index,
871 source_location location)
872 : Statement(STATEMENT_TUPLE_MAP_ASSIGNMENT, location),
873 val_(val), present_(present), map_index_(map_index)
878 do_traverse(Traverse* traverse);
881 do_traverse_assignments(Traverse_assignments*)
882 { gcc_unreachable(); }
885 do_lower(Gogo*, Block*);
888 do_get_tree(Translate_context*)
889 { gcc_unreachable(); }
892 // Lvalue which receives the value from the map.
894 // Lvalue which receives whether the key value was present.
895 Expression* present_;
896 // The map index expression.
897 Expression* map_index_;
903 Tuple_map_assignment_statement::do_traverse(Traverse* traverse)
905 if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT
906 || this->traverse_expression(traverse, &this->present_) == TRAVERSE_EXIT)
907 return TRAVERSE_EXIT;
908 return this->traverse_expression(traverse, &this->map_index_);
911 // Lower a tuple map assignment.
914 Tuple_map_assignment_statement::do_lower(Gogo*, Block* enclosing)
916 source_location loc = this->location();
918 Map_index_expression* map_index = this->map_index_->map_index_expression();
919 if (map_index == NULL)
921 this->report_error(_("expected map index on right hand side"));
922 return Statement::make_error_statement(loc);
924 Map_type* map_type = map_index->get_map_type();
925 if (map_type == NULL)
926 return Statement::make_error_statement(loc);
928 Block* b = new Block(enclosing, loc);
930 // Move out any subexpressions to make sure that functions are
931 // called in the required order.
932 Move_ordered_evals moe(b);
933 this->val_->traverse_subexpressions(&moe);
934 this->present_->traverse_subexpressions(&moe);
936 // Copy the key value into a temporary so that we can take its
937 // address without pushing the value onto the heap.
939 // var key_temp KEY_TYPE = MAP_INDEX
940 Temporary_statement* key_temp =
941 Statement::make_temporary(map_type->key_type(), map_index->index(), loc);
942 b->add_statement(key_temp);
944 // var val_temp VAL_TYPE
945 Temporary_statement* val_temp =
946 Statement::make_temporary(map_type->val_type(), NULL, loc);
947 b->add_statement(val_temp);
949 // var present_temp bool
950 Temporary_statement* present_temp =
951 Statement::make_temporary(Type::lookup_bool_type(), NULL, loc);
952 b->add_statement(present_temp);
954 // func mapaccess2(hmap map[k]v, key *k, val *v) bool
955 source_location bloc = BUILTINS_LOCATION;
956 Typed_identifier_list* param_types = new Typed_identifier_list();
957 param_types->push_back(Typed_identifier("hmap", map_type, bloc));
958 Type* pkey_type = Type::make_pointer_type(map_type->key_type());
959 param_types->push_back(Typed_identifier("key", pkey_type, bloc));
960 Type* pval_type = Type::make_pointer_type(map_type->val_type());
961 param_types->push_back(Typed_identifier("val", pval_type, bloc));
963 Typed_identifier_list* ret_types = new Typed_identifier_list();
964 ret_types->push_back(Typed_identifier("", Type::make_boolean_type(), bloc));
966 Function_type* fntype = Type::make_function_type(NULL, param_types,
968 Named_object* mapaccess2 =
969 Named_object::make_function_declaration("mapaccess2", NULL, fntype, bloc);
970 mapaccess2->func_declaration_value()->set_asm_name("runtime.mapaccess2");
972 // present_temp = mapaccess2(MAP, &key_temp, &val_temp)
973 Expression* func = Expression::make_func_reference(mapaccess2, NULL, loc);
974 Expression_list* params = new Expression_list();
975 params->push_back(map_index->map());
976 Expression* ref = Expression::make_temporary_reference(key_temp, loc);
977 params->push_back(Expression::make_unary(OPERATOR_AND, ref, loc));
978 ref = Expression::make_temporary_reference(val_temp, loc);
979 params->push_back(Expression::make_unary(OPERATOR_AND, ref, loc));
980 Expression* call = Expression::make_call(func, params, false, loc);
982 ref = Expression::make_temporary_reference(present_temp, loc);
983 Statement* s = Statement::make_assignment(ref, call, loc);
987 ref = Expression::make_temporary_reference(val_temp, loc);
988 s = Statement::make_assignment(this->val_, ref, loc);
991 // present = present_temp
992 ref = Expression::make_temporary_reference(present_temp, loc);
993 s = Statement::make_assignment(this->present_, ref, loc);
996 return Statement::make_block_statement(b, loc);
999 // Make a map assignment statement which returns a pair of values.
1002 Statement::make_tuple_map_assignment(Expression* val, Expression* present,
1003 Expression* map_index,
1004 source_location location)
1006 return new Tuple_map_assignment_statement(val, present, map_index, location);
1009 // Assign a pair of entries to a map.
1012 class Map_assignment_statement : public Statement
1015 Map_assignment_statement(Expression* map_index,
1016 Expression* val, Expression* should_set,
1017 source_location location)
1018 : Statement(STATEMENT_MAP_ASSIGNMENT, location),
1019 map_index_(map_index), val_(val), should_set_(should_set)
1024 do_traverse(Traverse* traverse);
1027 do_traverse_assignments(Traverse_assignments*)
1028 { gcc_unreachable(); }
1031 do_lower(Gogo*, Block*);
1034 do_get_tree(Translate_context*)
1035 { gcc_unreachable(); }
1038 // A reference to the map index which should be set or deleted.
1039 Expression* map_index_;
1040 // The value to add to the map.
1042 // Whether or not to add the value.
1043 Expression* should_set_;
1046 // Traverse a map assignment.
1049 Map_assignment_statement::do_traverse(Traverse* traverse)
1051 if (this->traverse_expression(traverse, &this->map_index_) == TRAVERSE_EXIT
1052 || this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT)
1053 return TRAVERSE_EXIT;
1054 return this->traverse_expression(traverse, &this->should_set_);
1057 // Lower a map assignment to a function call.
1060 Map_assignment_statement::do_lower(Gogo*, Block* enclosing)
1062 source_location loc = this->location();
1064 Map_index_expression* map_index = this->map_index_->map_index_expression();
1065 if (map_index == NULL)
1067 this->report_error(_("expected map index on left hand side"));
1068 return Statement::make_error_statement(loc);
1070 Map_type* map_type = map_index->get_map_type();
1071 if (map_type == NULL)
1072 return Statement::make_error_statement(loc);
1074 Block* b = new Block(enclosing, loc);
1076 // Evaluate the map first to get order of evaluation right.
1077 // map_temp := m // we are evaluating m[k] = v, p
1078 Temporary_statement* map_temp = Statement::make_temporary(map_type,
1081 b->add_statement(map_temp);
1083 // var key_temp MAP_KEY_TYPE = k
1084 Temporary_statement* key_temp =
1085 Statement::make_temporary(map_type->key_type(), map_index->index(), loc);
1086 b->add_statement(key_temp);
1088 // var val_temp MAP_VAL_TYPE = v
1089 Temporary_statement* val_temp =
1090 Statement::make_temporary(map_type->val_type(), this->val_, loc);
1091 b->add_statement(val_temp);
1093 // func mapassign2(hmap map[k]v, key *k, val *v, p)
1094 source_location bloc = BUILTINS_LOCATION;
1095 Typed_identifier_list* param_types = new Typed_identifier_list();
1096 param_types->push_back(Typed_identifier("hmap", map_type, bloc));
1097 Type* pkey_type = Type::make_pointer_type(map_type->key_type());
1098 param_types->push_back(Typed_identifier("key", pkey_type, bloc));
1099 Type* pval_type = Type::make_pointer_type(map_type->val_type());
1100 param_types->push_back(Typed_identifier("val", pval_type, bloc));
1101 param_types->push_back(Typed_identifier("p", Type::lookup_bool_type(), bloc));
1102 Function_type* fntype = Type::make_function_type(NULL, param_types,
1104 Named_object* mapassign2 =
1105 Named_object::make_function_declaration("mapassign2", NULL, fntype, bloc);
1106 mapassign2->func_declaration_value()->set_asm_name("runtime.mapassign2");
1108 // mapassign2(map_temp, &key_temp, &val_temp, p)
1109 Expression* func = Expression::make_func_reference(mapassign2, NULL, loc);
1110 Expression_list* params = new Expression_list();
1111 params->push_back(Expression::make_temporary_reference(map_temp, loc));
1112 Expression* ref = Expression::make_temporary_reference(key_temp, loc);
1113 params->push_back(Expression::make_unary(OPERATOR_AND, ref, loc));
1114 ref = Expression::make_temporary_reference(val_temp, loc);
1115 params->push_back(Expression::make_unary(OPERATOR_AND, ref, loc));
1116 params->push_back(this->should_set_);
1117 Expression* call = Expression::make_call(func, params, false, loc);
1118 Statement* s = Statement::make_statement(call);
1119 b->add_statement(s);
1121 return Statement::make_block_statement(b, loc);
1124 // Make a statement which assigns a pair of entries to a map.
1127 Statement::make_map_assignment(Expression* map_index,
1128 Expression* val, Expression* should_set,
1129 source_location location)
1131 return new Map_assignment_statement(map_index, val, should_set, location);
1134 // A tuple assignment from a receive statement.
1136 class Tuple_receive_assignment_statement : public Statement
1139 Tuple_receive_assignment_statement(Expression* val, Expression* success,
1140 Expression* channel,
1141 source_location location)
1142 : Statement(STATEMENT_TUPLE_RECEIVE_ASSIGNMENT, location),
1143 val_(val), success_(success), channel_(channel)
1148 do_traverse(Traverse* traverse);
1151 do_traverse_assignments(Traverse_assignments*)
1152 { gcc_unreachable(); }
1155 do_lower(Gogo*, Block*);
1158 do_get_tree(Translate_context*)
1159 { gcc_unreachable(); }
1162 // Lvalue which receives the value from the channel.
1164 // Lvalue which receives whether the read succeeded or failed.
1165 Expression* success_;
1166 // The channel on which we receive the value.
1167 Expression* channel_;
1173 Tuple_receive_assignment_statement::do_traverse(Traverse* traverse)
1175 if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT
1176 || this->traverse_expression(traverse, &this->success_) == TRAVERSE_EXIT)
1177 return TRAVERSE_EXIT;
1178 return this->traverse_expression(traverse, &this->channel_);
1181 // Lower to a function call.
1184 Tuple_receive_assignment_statement::do_lower(Gogo*, Block* enclosing)
1186 source_location loc = this->location();
1188 Channel_type* channel_type = this->channel_->type()->channel_type();
1189 if (channel_type == NULL)
1191 this->report_error(_("expected channel"));
1192 return Statement::make_error_statement(loc);
1194 if (!channel_type->may_receive())
1196 this->report_error(_("invalid receive on send-only channel"));
1197 return Statement::make_error_statement(loc);
1200 Block* b = new Block(enclosing, loc);
1202 // Make sure that any subexpressions on the left hand side are
1203 // evaluated in the right order.
1204 Move_ordered_evals moe(b);
1205 this->val_->traverse_subexpressions(&moe);
1206 this->success_->traverse_subexpressions(&moe);
1208 // var val_temp ELEMENT_TYPE
1209 Temporary_statement* val_temp =
1210 Statement::make_temporary(channel_type->element_type(), NULL, loc);
1211 b->add_statement(val_temp);
1213 // var success_temp bool
1214 Temporary_statement* success_temp =
1215 Statement::make_temporary(Type::lookup_bool_type(), NULL, loc);
1216 b->add_statement(success_temp);
1218 // func chanrecv2(c chan T, val *T) bool
1219 source_location bloc = BUILTINS_LOCATION;
1220 Typed_identifier_list* param_types = new Typed_identifier_list();
1221 param_types->push_back(Typed_identifier("c", channel_type, bloc));
1222 Type* pelement_type = Type::make_pointer_type(channel_type->element_type());
1223 param_types->push_back(Typed_identifier("val", pelement_type, bloc));
1225 Typed_identifier_list* ret_types = new Typed_identifier_list();
1226 ret_types->push_back(Typed_identifier("", Type::lookup_bool_type(), bloc));
1228 Function_type* fntype = Type::make_function_type(NULL, param_types,
1230 Named_object* chanrecv2 =
1231 Named_object::make_function_declaration("chanrecv2", NULL, fntype, bloc);
1232 chanrecv2->func_declaration_value()->set_asm_name("runtime.chanrecv2");
1234 // success_temp = chanrecv2(channel, &val_temp)
1235 Expression* func = Expression::make_func_reference(chanrecv2, NULL, loc);
1236 Expression_list* params = new Expression_list();
1237 params->push_back(this->channel_);
1238 Expression* ref = Expression::make_temporary_reference(val_temp, loc);
1239 params->push_back(Expression::make_unary(OPERATOR_AND, ref, loc));
1240 Expression* call = Expression::make_call(func, params, false, loc);
1241 ref = Expression::make_temporary_reference(success_temp, loc);
1242 Statement* s = Statement::make_assignment(ref, call, loc);
1243 b->add_statement(s);
1246 ref = Expression::make_temporary_reference(val_temp, loc);
1247 s = Statement::make_assignment(this->val_, ref, loc);
1248 b->add_statement(s);
1250 // success = success_temp
1251 ref = Expression::make_temporary_reference(success_temp, loc);
1252 s = Statement::make_assignment(this->success_, ref, loc);
1253 b->add_statement(s);
1255 return Statement::make_block_statement(b, loc);
1258 // Make a nonblocking receive statement.
1261 Statement::make_tuple_receive_assignment(Expression* val, Expression* success,
1262 Expression* channel,
1263 source_location location)
1265 return new Tuple_receive_assignment_statement(val, success, channel,
1269 // An assignment to a pair of values from a type guard. This is a
1270 // conditional type guard. v, ok = i.(type).
1272 class Tuple_type_guard_assignment_statement : public Statement
1275 Tuple_type_guard_assignment_statement(Expression* val, Expression* ok,
1276 Expression* expr, Type* type,
1277 source_location location)
1278 : Statement(STATEMENT_TUPLE_TYPE_GUARD_ASSIGNMENT, location),
1279 val_(val), ok_(ok), expr_(expr), type_(type)
1284 do_traverse(Traverse*);
1287 do_traverse_assignments(Traverse_assignments*)
1288 { gcc_unreachable(); }
1291 do_lower(Gogo*, Block*);
1294 do_get_tree(Translate_context*)
1295 { gcc_unreachable(); }
1299 lower_to_empty_interface(const char*);
1302 lower_to_type(const char*);
1305 lower_to_object_type(Block*, const char*);
1307 // The variable which recieves the converted value.
1309 // The variable which receives the indication of success.
1311 // The expression being converted.
1313 // The type to which the expression is being converted.
1317 // Traverse a type guard tuple assignment.
1320 Tuple_type_guard_assignment_statement::do_traverse(Traverse* traverse)
1322 if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT
1323 || this->traverse_expression(traverse, &this->ok_) == TRAVERSE_EXIT
1324 || this->traverse_type(traverse, this->type_) == TRAVERSE_EXIT)
1325 return TRAVERSE_EXIT;
1326 return this->traverse_expression(traverse, &this->expr_);
1329 // Lower to a function call.
1332 Tuple_type_guard_assignment_statement::do_lower(Gogo*, Block* enclosing)
1334 source_location loc = this->location();
1336 Type* expr_type = this->expr_->type();
1337 if (expr_type->interface_type() == NULL)
1339 if (!expr_type->is_error_type() && !this->type_->is_error_type())
1340 this->report_error(_("type assertion only valid for interface types"));
1341 return Statement::make_error_statement(loc);
1344 Block* b = new Block(enclosing, loc);
1346 // Make sure that any subexpressions on the left hand side are
1347 // evaluated in the right order.
1348 Move_ordered_evals moe(b);
1349 this->val_->traverse_subexpressions(&moe);
1350 this->ok_->traverse_subexpressions(&moe);
1352 bool expr_is_empty = expr_type->interface_type()->is_empty();
1353 Call_expression* call;
1354 if (this->type_->interface_type() != NULL)
1356 if (this->type_->interface_type()->is_empty())
1357 call = this->lower_to_empty_interface(expr_is_empty
1361 call = this->lower_to_type(expr_is_empty ? "ifaceE2I2" : "ifaceI2I2");
1363 else if (this->type_->points_to() != NULL)
1364 call = this->lower_to_type(expr_is_empty ? "ifaceE2T2P" : "ifaceI2T2P");
1367 this->lower_to_object_type(b, expr_is_empty ? "ifaceE2T2" : "ifaceI2T2");
1373 Expression* res = Expression::make_call_result(call, 0);
1374 Statement* s = Statement::make_assignment(this->val_, res, loc);
1375 b->add_statement(s);
1377 res = Expression::make_call_result(call, 1);
1378 s = Statement::make_assignment(this->ok_, res, loc);
1379 b->add_statement(s);
1382 return Statement::make_block_statement(b, loc);
1385 // Lower a conversion to an empty interface type.
1388 Tuple_type_guard_assignment_statement::lower_to_empty_interface(
1391 source_location loc = this->location();
1393 // func FNNAME(interface) (empty, bool)
1394 source_location bloc = BUILTINS_LOCATION;
1395 Typed_identifier_list* param_types = new Typed_identifier_list();
1396 param_types->push_back(Typed_identifier("i", this->expr_->type(), bloc));
1397 Typed_identifier_list* ret_types = new Typed_identifier_list();
1398 ret_types->push_back(Typed_identifier("ret", this->type_, bloc));
1399 ret_types->push_back(Typed_identifier("ok", Type::lookup_bool_type(), bloc));
1400 Function_type* fntype = Type::make_function_type(NULL, param_types,
1403 Named_object::make_function_declaration(fnname, NULL, fntype, bloc);
1404 std::string asm_name = "runtime.";
1406 fn->func_declaration_value()->set_asm_name(asm_name);
1408 // val, ok = FNNAME(expr)
1409 Expression* func = Expression::make_func_reference(fn, NULL, loc);
1410 Expression_list* params = new Expression_list();
1411 params->push_back(this->expr_);
1412 return Expression::make_call(func, params, false, loc);
1415 // Lower a conversion to a non-empty interface type or a pointer type.
1418 Tuple_type_guard_assignment_statement::lower_to_type(const char* fnname)
1420 source_location loc = this->location();
1422 // func FNNAME(*descriptor, interface) (interface, bool)
1423 source_location bloc = BUILTINS_LOCATION;
1424 Typed_identifier_list* param_types = new Typed_identifier_list();
1425 param_types->push_back(Typed_identifier("inter",
1426 Type::make_type_descriptor_ptr_type(),
1428 param_types->push_back(Typed_identifier("i", this->expr_->type(), bloc));
1429 Typed_identifier_list* ret_types = new Typed_identifier_list();
1430 ret_types->push_back(Typed_identifier("ret", this->type_, bloc));
1431 ret_types->push_back(Typed_identifier("ok", Type::lookup_bool_type(), bloc));
1432 Function_type* fntype = Type::make_function_type(NULL, param_types,
1435 Named_object::make_function_declaration(fnname, NULL, fntype, bloc);
1436 std::string asm_name = "runtime.";
1438 fn->func_declaration_value()->set_asm_name(asm_name);
1440 // val, ok = FNNAME(type_descriptor, expr)
1441 Expression* func = Expression::make_func_reference(fn, NULL, loc);
1442 Expression_list* params = new Expression_list();
1443 params->push_back(Expression::make_type_descriptor(this->type_, loc));
1444 params->push_back(this->expr_);
1445 return Expression::make_call(func, params, false, loc);
1448 // Lower a conversion to a non-interface non-pointer type.
1451 Tuple_type_guard_assignment_statement::lower_to_object_type(Block* b,
1454 source_location loc = this->location();
1456 // var val_temp TYPE
1457 Temporary_statement* val_temp = Statement::make_temporary(this->type_,
1459 b->add_statement(val_temp);
1461 // func FNNAME(*descriptor, interface, *T) bool
1462 source_location bloc = BUILTINS_LOCATION;
1463 Typed_identifier_list* param_types = new Typed_identifier_list();
1464 param_types->push_back(Typed_identifier("inter",
1465 Type::make_type_descriptor_ptr_type(),
1467 param_types->push_back(Typed_identifier("i", this->expr_->type(), bloc));
1468 Type* ptype = Type::make_pointer_type(this->type_);
1469 param_types->push_back(Typed_identifier("v", ptype, bloc));
1470 Typed_identifier_list* ret_types = new Typed_identifier_list();
1471 ret_types->push_back(Typed_identifier("ok", Type::lookup_bool_type(), bloc));
1472 Function_type* fntype = Type::make_function_type(NULL, param_types,
1475 Named_object::make_function_declaration(fnname, NULL, fntype, bloc);
1476 std::string asm_name = "runtime.";
1478 fn->func_declaration_value()->set_asm_name(asm_name);
1480 // ok = FNNAME(type_descriptor, expr, &val_temp)
1481 Expression* func = Expression::make_func_reference(fn, NULL, loc);
1482 Expression_list* params = new Expression_list();
1483 params->push_back(Expression::make_type_descriptor(this->type_, loc));
1484 params->push_back(this->expr_);
1485 Expression* ref = Expression::make_temporary_reference(val_temp, loc);
1486 params->push_back(Expression::make_unary(OPERATOR_AND, ref, loc));
1487 Expression* call = Expression::make_call(func, params, false, loc);
1488 Statement* s = Statement::make_assignment(this->ok_, call, loc);
1489 b->add_statement(s);
1492 ref = Expression::make_temporary_reference(val_temp, loc);
1493 s = Statement::make_assignment(this->val_, ref, loc);
1494 b->add_statement(s);
1497 // Make an assignment from a type guard to a pair of variables.
1500 Statement::make_tuple_type_guard_assignment(Expression* val, Expression* ok,
1501 Expression* expr, Type* type,
1502 source_location location)
1504 return new Tuple_type_guard_assignment_statement(val, ok, expr, type,
1508 // An expression statement.
1510 class Expression_statement : public Statement
1513 Expression_statement(Expression* expr)
1514 : Statement(STATEMENT_EXPRESSION, expr->location()),
1520 do_traverse(Traverse* traverse)
1521 { return this->traverse_expression(traverse, &this->expr_); }
1524 do_determine_types()
1525 { this->expr_->determine_type_no_context(); }
1528 do_may_fall_through() const;
1531 do_get_tree(Translate_context* context)
1532 { return this->expr_->get_tree(context); }
1538 // An expression statement may fall through unless it is a call to a
1539 // function which does not return.
1542 Expression_statement::do_may_fall_through() const
1544 const Call_expression* call = this->expr_->call_expression();
1547 const Expression* fn = call->fn();
1548 const Func_expression* fe = fn->func_expression();
1551 const Named_object* no = fe->named_object();
1553 Function_type* fntype;
1554 if (no->is_function())
1555 fntype = no->func_value()->type();
1556 else if (no->is_function_declaration())
1557 fntype = no->func_declaration_value()->type();
1561 // The builtin function panic does not return.
1562 if (fntype != NULL && fntype->is_builtin() && no->name() == "panic")
1569 // Make an expression statement from an Expression.
1572 Statement::make_statement(Expression* expr)
1574 return new Expression_statement(expr);
1577 // A block statement--a list of statements which may include variable
1580 class Block_statement : public Statement
1583 Block_statement(Block* block, source_location location)
1584 : Statement(STATEMENT_BLOCK, location),
1590 do_traverse(Traverse* traverse)
1591 { return this->block_->traverse(traverse); }
1594 do_determine_types()
1595 { this->block_->determine_types(); }
1598 do_may_fall_through() const
1599 { return this->block_->may_fall_through(); }
1602 do_get_tree(Translate_context* context)
1603 { return this->block_->get_tree(context); }
1609 // Make a block statement.
1612 Statement::make_block_statement(Block* block, source_location location)
1614 return new Block_statement(block, location);
1617 // An increment or decrement statement.
1619 class Inc_dec_statement : public Statement
1622 Inc_dec_statement(bool is_inc, Expression* expr)
1623 : Statement(STATEMENT_INCDEC, expr->location()),
1624 expr_(expr), is_inc_(is_inc)
1629 do_traverse(Traverse* traverse)
1630 { return this->traverse_expression(traverse, &this->expr_); }
1633 do_traverse_assignments(Traverse_assignments*)
1634 { gcc_unreachable(); }
1637 do_lower(Gogo*, Block*);
1640 do_get_tree(Translate_context*)
1641 { gcc_unreachable(); }
1644 // The l-value to increment or decrement.
1646 // Whether to increment or decrement.
1650 // Lower to += or -=.
1653 Inc_dec_statement::do_lower(Gogo*, Block*)
1655 source_location loc = this->location();
1658 mpz_init_set_ui(oval, 1UL);
1659 Expression* oexpr = Expression::make_integer(&oval, NULL, loc);
1662 Operator op = this->is_inc_ ? OPERATOR_PLUSEQ : OPERATOR_MINUSEQ;
1663 return Statement::make_assignment_operation(op, this->expr_, oexpr, loc);
1666 // Make an increment statement.
1669 Statement::make_inc_statement(Expression* expr)
1671 return new Inc_dec_statement(true, expr);
1674 // Make a decrement statement.
1677 Statement::make_dec_statement(Expression* expr)
1679 return new Inc_dec_statement(false, expr);
1682 // Class Thunk_statement. This is the base class for go and defer
1685 const char* const Thunk_statement::thunk_field_fn = "fn";
1687 const char* const Thunk_statement::thunk_field_receiver = "receiver";
1691 Thunk_statement::Thunk_statement(Statement_classification classification,
1692 Call_expression* call,
1693 source_location location)
1694 : Statement(classification, location),
1695 call_(call), struct_type_(NULL)
1699 // Return whether this is a simple statement which does not require a
1703 Thunk_statement::is_simple(Function_type* fntype) const
1705 // We need a thunk to call a method, or to pass a variable number of
1707 if (fntype->is_method() || fntype->is_varargs())
1710 // A defer statement requires a thunk to set up for whether the
1711 // function can call recover.
1712 if (this->classification() == STATEMENT_DEFER)
1715 // We can only permit a single parameter of pointer type.
1716 const Typed_identifier_list* parameters = fntype->parameters();
1717 if (parameters != NULL
1718 && (parameters->size() > 1
1719 || (parameters->size() == 1
1720 && parameters->begin()->type()->points_to() == NULL)))
1723 // If the function returns multiple values, or returns a type other
1724 // than integer, floating point, or pointer, then it may get a
1725 // hidden first parameter, in which case we need the more
1726 // complicated approach. This is true even though we are going to
1727 // ignore the return value.
1728 const Typed_identifier_list* results = fntype->results();
1730 && (results->size() > 1
1731 || (results->size() == 1
1732 && !results->begin()->type()->is_basic_type()
1733 && results->begin()->type()->points_to() == NULL)))
1736 // If this calls something which is not a simple function, then we
1738 Expression* fn = this->call_->call_expression()->fn();
1739 if (fn->bound_method_expression() != NULL
1740 || fn->interface_field_reference_expression() != NULL)
1746 // Traverse a thunk statement.
1749 Thunk_statement::do_traverse(Traverse* traverse)
1751 return this->traverse_expression(traverse, &this->call_);
1754 // We implement traverse_assignment for a thunk statement because it
1755 // effectively copies the function call.
1758 Thunk_statement::do_traverse_assignments(Traverse_assignments* tassign)
1760 Expression* fn = this->call_->call_expression()->fn();
1761 Expression* fn2 = fn;
1762 tassign->value(&fn2, true, false);
1766 // Determine types in a thunk statement.
1769 Thunk_statement::do_determine_types()
1771 this->call_->determine_type_no_context();
1773 // Now that we know the types of the call, build the struct used to
1775 Function_type* fntype =
1776 this->call_->call_expression()->get_function_type();
1777 if (fntype != NULL && !this->is_simple(fntype))
1778 this->struct_type_ = this->build_struct(fntype);
1781 // Check types in a thunk statement.
1784 Thunk_statement::do_check_types(Gogo*)
1786 Call_expression* ce = this->call_->call_expression();
1787 Function_type* fntype = ce->get_function_type();
1788 if (fntype != NULL && fntype->is_method())
1790 Expression* fn = ce->fn();
1791 if (fn->bound_method_expression() == NULL
1792 && fn->interface_field_reference_expression() == NULL)
1793 this->report_error(_("no object for method call"));
1797 // The Traverse class used to find and simplify thunk statements.
1799 class Simplify_thunk_traverse : public Traverse
1802 Simplify_thunk_traverse(Gogo* gogo)
1803 : Traverse(traverse_blocks),
1815 Simplify_thunk_traverse::block(Block* b)
1817 // The parser ensures that thunk statements always appear at the end
1819 if (b->statements()->size() < 1)
1820 return TRAVERSE_CONTINUE;
1821 Thunk_statement* stat = b->statements()->back()->thunk_statement();
1823 return TRAVERSE_CONTINUE;
1824 if (stat->simplify_statement(this->gogo_, b))
1825 return TRAVERSE_SKIP_COMPONENTS;
1826 return TRAVERSE_CONTINUE;
1829 // Simplify all thunk statements.
1832 Gogo::simplify_thunk_statements()
1834 Simplify_thunk_traverse thunk_traverse(this);
1835 this->traverse(&thunk_traverse);
1838 // Simplify complex thunk statements into simple ones. A complicated
1839 // thunk statement is one which takes anything other than zero
1840 // parameters or a single pointer parameter. We rewrite it into code
1841 // which allocates a struct, stores the parameter values into the
1842 // struct, and does a simple go or defer statement which passes the
1843 // struct to a thunk. The thunk does the real call.
1846 Thunk_statement::simplify_statement(Gogo* gogo, Block* block)
1848 if (this->classification() == STATEMENT_ERROR)
1850 if (this->call_->is_error_expression())
1853 Call_expression* ce = this->call_->call_expression();
1854 Function_type* fntype = ce->get_function_type();
1857 gcc_assert(saw_errors());
1858 this->set_is_error();
1861 if (this->is_simple(fntype))
1864 Expression* fn = ce->fn();
1865 Bound_method_expression* bound_method = fn->bound_method_expression();
1866 Interface_field_reference_expression* interface_method =
1867 fn->interface_field_reference_expression();
1868 const bool is_method = bound_method != NULL || interface_method != NULL;
1870 source_location location = this->location();
1872 std::string thunk_name = Gogo::thunk_name();
1875 this->build_thunk(gogo, thunk_name, fntype);
1877 // Generate code to call the thunk.
1879 // Get the values to store into the struct which is the single
1880 // argument to the thunk.
1882 Expression_list* vals = new Expression_list();
1883 if (fntype->is_builtin())
1885 else if (!is_method)
1886 vals->push_back(fn);
1887 else if (interface_method != NULL)
1888 vals->push_back(interface_method->expr());
1889 else if (bound_method != NULL)
1891 vals->push_back(bound_method->method());
1892 Expression* first_arg = bound_method->first_argument();
1894 // We always pass a pointer when calling a method.
1895 if (first_arg->type()->points_to() == NULL)
1896 first_arg = Expression::make_unary(OPERATOR_AND, first_arg, location);
1898 // If we are calling a method which was inherited from an
1899 // embedded struct, and the method did not get a stub, then the
1900 // first type may be wrong.
1901 Type* fatype = bound_method->first_argument_type();
1904 if (fatype->points_to() == NULL)
1905 fatype = Type::make_pointer_type(fatype);
1906 Type* unsafe = Type::make_pointer_type(Type::make_void_type());
1907 first_arg = Expression::make_cast(unsafe, first_arg, location);
1908 first_arg = Expression::make_cast(fatype, first_arg, location);
1911 vals->push_back(first_arg);
1916 if (ce->args() != NULL)
1918 for (Expression_list::const_iterator p = ce->args()->begin();
1919 p != ce->args()->end();
1921 vals->push_back(*p);
1924 // Build the struct.
1925 Expression* constructor =
1926 Expression::make_struct_composite_literal(this->struct_type_, vals,
1929 // Allocate the initialized struct on the heap.
1930 constructor = Expression::make_heap_composite(constructor, location);
1932 // Look up the thunk.
1933 Named_object* named_thunk = gogo->lookup(thunk_name, NULL);
1934 gcc_assert(named_thunk != NULL && named_thunk->is_function());
1937 Expression* func = Expression::make_func_reference(named_thunk, NULL,
1939 Expression_list* params = new Expression_list();
1940 params->push_back(constructor);
1941 Call_expression* call = Expression::make_call(func, params, false, location);
1943 // Build the simple go or defer statement.
1945 if (this->classification() == STATEMENT_GO)
1946 s = Statement::make_go_statement(call, location);
1947 else if (this->classification() == STATEMENT_DEFER)
1948 s = Statement::make_defer_statement(call, location);
1952 // The current block should end with the go statement.
1953 gcc_assert(block->statements()->size() >= 1);
1954 gcc_assert(block->statements()->back() == this);
1955 block->replace_statement(block->statements()->size() - 1, s);
1957 // We already ran the determine_types pass, so we need to run it now
1958 // for the new statement.
1959 s->determine_types();
1962 gogo->check_types_in_block(block);
1964 // Return true to tell the block not to keep looking at statements.
1968 // Set the name to use for thunk parameter N.
1971 Thunk_statement::thunk_field_param(int n, char* buf, size_t buflen)
1973 snprintf(buf, buflen, "a%d", n);
1976 // Build a new struct type to hold the parameters for a complicated
1977 // thunk statement. FNTYPE is the type of the function call.
1980 Thunk_statement::build_struct(Function_type* fntype)
1982 source_location location = this->location();
1984 Struct_field_list* fields = new Struct_field_list();
1986 Call_expression* ce = this->call_->call_expression();
1987 Expression* fn = ce->fn();
1989 Interface_field_reference_expression* interface_method =
1990 fn->interface_field_reference_expression();
1991 if (interface_method != NULL)
1993 // If this thunk statement calls a method on an interface, we
1994 // pass the interface object to the thunk.
1995 Typed_identifier tid(Thunk_statement::thunk_field_fn,
1996 interface_method->expr()->type(),
1998 fields->push_back(Struct_field(tid));
2000 else if (!fntype->is_builtin())
2002 // The function to call.
2003 Typed_identifier tid(Go_statement::thunk_field_fn, fntype, location);
2004 fields->push_back(Struct_field(tid));
2006 else if (ce->is_recover_call())
2008 // The predeclared recover function has no argument. However,
2009 // we add an argument when building recover thunks. Handle that
2011 fields->push_back(Struct_field(Typed_identifier("can_recover",
2012 Type::make_boolean_type(),
2016 if (fn->bound_method_expression() != NULL)
2018 gcc_assert(fntype->is_method());
2019 Type* rtype = fntype->receiver()->type();
2020 // We always pass the receiver as a pointer.
2021 if (rtype->points_to() == NULL)
2022 rtype = Type::make_pointer_type(rtype);
2023 Typed_identifier tid(Thunk_statement::thunk_field_receiver, rtype,
2025 fields->push_back(Struct_field(tid));
2028 const Expression_list* args = ce->args();
2032 for (Expression_list::const_iterator p = args->begin();
2037 this->thunk_field_param(i, buf, sizeof buf);
2038 fields->push_back(Struct_field(Typed_identifier(buf, (*p)->type(),
2043 return Type::make_struct_type(fields, location);
2046 // Build the thunk we are going to call. This is a brand new, albeit
2047 // artificial, function.
2050 Thunk_statement::build_thunk(Gogo* gogo, const std::string& thunk_name,
2051 Function_type* fntype)
2053 source_location location = this->location();
2055 Call_expression* ce = this->call_->call_expression();
2057 bool may_call_recover = false;
2058 if (this->classification() == STATEMENT_DEFER)
2060 Func_expression* fn = ce->fn()->func_expression();
2062 may_call_recover = true;
2065 const Named_object* no = fn->named_object();
2066 if (!no->is_function())
2067 may_call_recover = true;
2069 may_call_recover = no->func_value()->calls_recover();
2073 // Build the type of the thunk. The thunk takes a single parameter,
2074 // which is a pointer to the special structure we build.
2075 const char* const parameter_name = "__go_thunk_parameter";
2076 Typed_identifier_list* thunk_parameters = new Typed_identifier_list();
2077 Type* pointer_to_struct_type = Type::make_pointer_type(this->struct_type_);
2078 thunk_parameters->push_back(Typed_identifier(parameter_name,
2079 pointer_to_struct_type,
2082 Typed_identifier_list* thunk_results = NULL;
2083 if (may_call_recover)
2085 // When deferring a function which may call recover, add a
2086 // return value, to disable tail call optimizations which will
2087 // break the way we check whether recover is permitted.
2088 thunk_results = new Typed_identifier_list();
2089 thunk_results->push_back(Typed_identifier("", Type::make_boolean_type(),
2093 Function_type* thunk_type = Type::make_function_type(NULL, thunk_parameters,
2097 // Start building the thunk.
2098 Named_object* function = gogo->start_function(thunk_name, thunk_type, true,
2101 // For a defer statement, start with a call to
2102 // __go_set_defer_retaddr. */
2103 Label* retaddr_label = NULL;
2104 if (may_call_recover)
2106 retaddr_label = gogo->add_label_reference("retaddr");
2107 Expression* arg = Expression::make_label_addr(retaddr_label, location);
2108 Expression_list* args = new Expression_list();
2109 args->push_back(arg);
2111 static Named_object* set_defer_retaddr;
2112 if (set_defer_retaddr == NULL)
2114 const source_location bloc = BUILTINS_LOCATION;
2115 Typed_identifier_list* param_types = new Typed_identifier_list();
2116 Type *voidptr_type = Type::make_pointer_type(Type::make_void_type());
2117 param_types->push_back(Typed_identifier("r", voidptr_type, bloc));
2119 Typed_identifier_list* result_types = new Typed_identifier_list();
2120 result_types->push_back(Typed_identifier("",
2121 Type::make_boolean_type(),
2124 Function_type* t = Type::make_function_type(NULL, param_types,
2125 result_types, bloc);
2127 Named_object::make_function_declaration("__go_set_defer_retaddr",
2129 const char* n = "__go_set_defer_retaddr";
2130 set_defer_retaddr->func_declaration_value()->set_asm_name(n);
2133 Expression* fn = Expression::make_func_reference(set_defer_retaddr,
2135 Expression* call = Expression::make_call(fn, args, false, location);
2137 // This is a hack to prevent the middle-end from deleting the
2139 gogo->start_block(location);
2140 gogo->add_statement(Statement::make_goto_statement(retaddr_label,
2142 Block* then_block = gogo->finish_block(location);
2143 then_block->determine_types();
2145 Statement* s = Statement::make_if_statement(call, then_block, NULL,
2147 s->determine_types();
2148 gogo->add_statement(s);
2151 // Get a reference to the parameter.
2152 Named_object* named_parameter = gogo->lookup(parameter_name, NULL);
2153 gcc_assert(named_parameter != NULL && named_parameter->is_variable());
2155 // Build the call. Note that the field names are the same as the
2156 // ones used in build_struct.
2157 Expression* thunk_parameter = Expression::make_var_reference(named_parameter,
2159 thunk_parameter = Expression::make_unary(OPERATOR_MULT, thunk_parameter,
2162 Bound_method_expression* bound_method = ce->fn()->bound_method_expression();
2163 Interface_field_reference_expression* interface_method =
2164 ce->fn()->interface_field_reference_expression();
2166 Expression* func_to_call;
2167 unsigned int next_index;
2168 if (!fntype->is_builtin())
2170 func_to_call = Expression::make_field_reference(thunk_parameter,
2176 gcc_assert(bound_method == NULL && interface_method == NULL);
2177 func_to_call = ce->fn();
2181 if (bound_method != NULL)
2183 Expression* r = Expression::make_field_reference(thunk_parameter, 1,
2185 // The main program passes in a function pointer from the
2186 // interface expression, so here we can make a bound method in
2188 func_to_call = Expression::make_bound_method(r, func_to_call,
2192 else if (interface_method != NULL)
2194 // The main program passes the interface object.
2195 const std::string& name(interface_method->name());
2196 func_to_call = Expression::make_interface_field_reference(func_to_call,
2201 Expression_list* call_params = new Expression_list();
2202 const Struct_field_list* fields = this->struct_type_->fields();
2203 Struct_field_list::const_iterator p = fields->begin();
2204 for (unsigned int i = 0; i < next_index; ++i)
2206 for (; p != fields->end(); ++p, ++next_index)
2208 Expression* thunk_param = Expression::make_var_reference(named_parameter,
2210 thunk_param = Expression::make_unary(OPERATOR_MULT, thunk_param,
2212 Expression* param = Expression::make_field_reference(thunk_param,
2215 call_params->push_back(param);
2218 Expression* call = Expression::make_call(func_to_call, call_params, false,
2220 // We need to lower in case this is a builtin function.
2221 call = call->lower(gogo, function, -1);
2222 if (may_call_recover)
2224 Call_expression* ce = call->call_expression();
2226 ce->set_is_deferred();
2229 Statement* call_statement = Statement::make_statement(call);
2231 // We already ran the determine_types pass, so we need to run it
2232 // just for this statement now.
2233 call_statement->determine_types();
2235 gogo->add_statement(call_statement);
2237 // If this is a defer statement, the label comes immediately after
2239 if (may_call_recover)
2241 gogo->add_label_definition("retaddr", location);
2243 Expression_list* vals = new Expression_list();
2244 vals->push_back(Expression::make_boolean(false, location));
2245 const Typed_identifier_list* results =
2246 function->func_value()->type()->results();
2247 gogo->add_statement(Statement::make_return_statement(results, vals,
2251 // That is all the thunk has to do.
2252 gogo->finish_function(location);
2255 // Get the function and argument trees.
2258 Thunk_statement::get_fn_and_arg(Translate_context* context, tree* pfn,
2261 if (this->call_->is_error_expression())
2263 *pfn = error_mark_node;
2264 *parg = error_mark_node;
2268 Call_expression* ce = this->call_->call_expression();
2270 Expression* fn = ce->fn();
2271 *pfn = fn->get_tree(context);
2273 const Expression_list* args = ce->args();
2274 if (args == NULL || args->empty())
2275 *parg = null_pointer_node;
2278 gcc_assert(args->size() == 1);
2279 *parg = args->front()->get_tree(context);
2283 // Class Go_statement.
2286 Go_statement::do_get_tree(Translate_context* context)
2290 this->get_fn_and_arg(context, &fn_tree, &arg_tree);
2292 static tree go_fndecl;
2294 tree fn_arg_type = NULL_TREE;
2295 if (go_fndecl == NULL_TREE)
2297 // Only build FN_ARG_TYPE if we need it.
2298 tree subargtypes = tree_cons(NULL_TREE, ptr_type_node, void_list_node);
2299 tree subfntype = build_function_type(ptr_type_node, subargtypes);
2300 fn_arg_type = build_pointer_type(subfntype);
2303 return Gogo::call_builtin(&go_fndecl,
2314 // Make a go statement.
2317 Statement::make_go_statement(Call_expression* call, source_location location)
2319 return new Go_statement(call, location);
2322 // Class Defer_statement.
2325 Defer_statement::do_get_tree(Translate_context* context)
2327 source_location loc = this->location();
2331 this->get_fn_and_arg(context, &fn_tree, &arg_tree);
2332 if (fn_tree == error_mark_node || arg_tree == error_mark_node)
2333 return error_mark_node;
2335 static tree defer_fndecl;
2337 tree fn_arg_type = NULL_TREE;
2338 if (defer_fndecl == NULL_TREE)
2340 // Only build FN_ARG_TYPE if we need it.
2341 tree subargtypes = tree_cons(NULL_TREE, ptr_type_node, void_list_node);
2342 tree subfntype = build_function_type(ptr_type_node, subargtypes);
2343 fn_arg_type = build_pointer_type(subfntype);
2346 tree defer_stack = context->function()->func_value()->defer_stack(loc);
2348 return Gogo::call_builtin(&defer_fndecl,
2361 // Make a defer statement.
2364 Statement::make_defer_statement(Call_expression* call,
2365 source_location location)
2367 return new Defer_statement(call, location);
2370 // Class Return_statement.
2372 // Traverse assignments. We treat each return value as a top level
2373 // RHS in an expression.
2376 Return_statement::do_traverse_assignments(Traverse_assignments* tassign)
2378 Expression_list* vals = this->vals_;
2381 for (Expression_list::iterator p = vals->begin();
2384 tassign->value(&*p, true, true);
2389 // Lower a return statement. If we are returning a function call
2390 // which returns multiple values which match the current function,
2391 // split up the call's results. If the function has named result
2392 // variables, and the return statement lists explicit values, then
2393 // implement it by assigning the values to the result variables and
2394 // changing the statement to not list any values. This lets
2395 // panic/recover work correctly.
2398 Return_statement::do_lower(Gogo*, Block* enclosing)
2400 if (this->vals_ == NULL)
2403 const Typed_identifier_list* results = this->results_;
2404 if (results == NULL || results->empty())
2407 // If the current function has multiple return values, and we are
2408 // returning a single call expression, split up the call expression.
2409 size_t results_count = results->size();
2410 if (results_count > 1
2411 && this->vals_->size() == 1
2412 && this->vals_->front()->call_expression() != NULL)
2414 Call_expression* call = this->vals_->front()->call_expression();
2415 size_t count = results->size();
2416 Expression_list* vals = new Expression_list;
2417 for (size_t i = 0; i < count; ++i)
2418 vals->push_back(Expression::make_call_result(call, i));
2423 if (results->front().name().empty())
2426 if (results_count != this->vals_->size())
2428 // Presumably an error which will be reported in check_types.
2432 // Assign to named return values and then return them.
2434 source_location loc = this->location();
2435 const Block* top = enclosing;
2436 while (top->enclosing() != NULL)
2437 top = top->enclosing();
2439 const Bindings *bindings = top->bindings();
2440 Block* b = new Block(enclosing, loc);
2442 Expression_list* lhs = new Expression_list();
2443 Expression_list* rhs = new Expression_list();
2445 Expression_list::const_iterator pe = this->vals_->begin();
2447 for (Typed_identifier_list::const_iterator pr = results->begin();
2448 pr != results->end();
2451 Named_object* rv = bindings->lookup_local(pr->name());
2452 if (rv == NULL || !rv->is_result_variable())
2454 // Presumably an error.
2461 Expression* e = *pe;
2463 // Check types now so that we give a good error message. The
2464 // result type is known. We determine the expression type
2467 Type *rvtype = rv->result_var_value()->type();
2468 Type_context type_context(rvtype, false);
2469 e->determine_type(&type_context);
2472 if (Type::are_assignable(rvtype, e->type(), &reason))
2474 Expression* ve = Expression::make_var_reference(rv, e->location());
2481 error_at(e->location(), "incompatible type for return value %d", i);
2483 error_at(e->location(),
2484 "incompatible type for return value %d (%s)",
2488 gcc_assert(lhs->size() == rhs->size());
2492 else if (lhs->size() == 1)
2494 b->add_statement(Statement::make_assignment(lhs->front(), rhs->front(),
2500 b->add_statement(Statement::make_tuple_assignment(lhs, rhs, loc));
2502 b->add_statement(Statement::make_return_statement(this->results_, NULL,
2505 return Statement::make_block_statement(b, loc);
2511 Return_statement::do_determine_types()
2513 if (this->vals_ == NULL)
2515 const Typed_identifier_list* results = this->results_;
2517 Typed_identifier_list::const_iterator pt;
2518 if (results != NULL)
2519 pt = results->begin();
2520 for (Expression_list::iterator pe = this->vals_->begin();
2521 pe != this->vals_->end();
2524 if (results == NULL || pt == results->end())
2525 (*pe)->determine_type_no_context();
2528 Type_context context(pt->type(), false);
2529 (*pe)->determine_type(&context);
2538 Return_statement::do_check_types(Gogo*)
2540 if (this->vals_ == NULL)
2543 const Typed_identifier_list* results = this->results_;
2544 if (results == NULL)
2546 this->report_error(_("return with value in function "
2547 "with no return type"));
2552 Typed_identifier_list::const_iterator pt = results->begin();
2553 for (Expression_list::const_iterator pe = this->vals_->begin();
2554 pe != this->vals_->end();
2557 if (pt == results->end())
2559 this->report_error(_("too many values in return statement"));
2563 if (!Type::are_assignable(pt->type(), (*pe)->type(), &reason))
2566 error_at(this->location(),
2567 "incompatible type for return value %d",
2570 error_at(this->location(),
2571 "incompatible type for return value %d (%s)",
2573 this->set_is_error();
2575 else if (pt->type()->is_error_type()
2576 || (*pe)->type()->is_error_type()
2577 || pt->type()->is_undefined()
2578 || (*pe)->type()->is_undefined())
2580 // Make sure we get the error for an undefined type.
2582 (*pe)->type()->base();
2583 this->set_is_error();
2587 if (pt != results->end())
2588 this->report_error(_("not enough values in return statement"));
2591 // Build a RETURN_EXPR tree.
2594 Return_statement::do_get_tree(Translate_context* context)
2596 Function* function = context->function()->func_value();
2597 tree fndecl = function->get_decl();
2598 if (fndecl == error_mark_node || DECL_RESULT(fndecl) == error_mark_node)
2599 return error_mark_node;
2601 const Typed_identifier_list* results = this->results_;
2603 if (this->vals_ == NULL)
2605 tree stmt_list = NULL_TREE;
2606 tree retval = function->return_value(context->gogo(),
2607 context->function(),
2611 if (retval == NULL_TREE)
2613 else if (retval == error_mark_node)
2614 return error_mark_node;
2616 set = fold_build2_loc(this->location(), MODIFY_EXPR, void_type_node,
2617 DECL_RESULT(fndecl), retval);
2618 append_to_statement_list(this->build_stmt_1(RETURN_EXPR, set),
2622 else if (this->vals_->size() == 1)
2624 gcc_assert(!VOID_TYPE_P(TREE_TYPE(TREE_TYPE(fndecl))));
2625 tree val = (*this->vals_->begin())->get_tree(context);
2626 gcc_assert(results != NULL && results->size() == 1);
2627 val = Expression::convert_for_assignment(context,
2628 results->begin()->type(),
2629 (*this->vals_->begin())->type(),
2630 val, this->location());
2631 if (val == error_mark_node)
2632 return error_mark_node;
2633 tree set = build2(MODIFY_EXPR, void_type_node,
2634 DECL_RESULT(fndecl), val);
2635 SET_EXPR_LOCATION(set, this->location());
2636 return this->build_stmt_1(RETURN_EXPR, set);
2640 gcc_assert(!VOID_TYPE_P(TREE_TYPE(TREE_TYPE(fndecl))));
2641 tree stmt_list = NULL_TREE;
2642 tree rettype = TREE_TYPE(DECL_RESULT(fndecl));
2643 tree retvar = create_tmp_var(rettype, "RESULT");
2644 gcc_assert(results != NULL && results->size() == this->vals_->size());
2645 Expression_list::const_iterator pv = this->vals_->begin();
2646 Typed_identifier_list::const_iterator pr = results->begin();
2647 for (tree field = TYPE_FIELDS(rettype);
2649 ++pv, ++pr, field = DECL_CHAIN(field))
2651 gcc_assert(pv != this->vals_->end());
2652 tree val = (*pv)->get_tree(context);
2653 val = Expression::convert_for_assignment(context, pr->type(),
2656 if (val == error_mark_node)
2657 return error_mark_node;
2658 tree set = build2(MODIFY_EXPR, void_type_node,
2659 build3(COMPONENT_REF, TREE_TYPE(field),
2660 retvar, field, NULL_TREE),
2662 SET_EXPR_LOCATION(set, this->location());
2663 append_to_statement_list(set, &stmt_list);
2665 tree set = build2(MODIFY_EXPR, void_type_node, DECL_RESULT(fndecl),
2667 append_to_statement_list(this->build_stmt_1(RETURN_EXPR, set),
2673 // Make a return statement.
2676 Statement::make_return_statement(const Typed_identifier_list* results,
2677 Expression_list* vals,
2678 source_location location)
2680 return new Return_statement(results, vals, location);
2683 // A break or continue statement.
2685 class Bc_statement : public Statement
2688 Bc_statement(bool is_break, Unnamed_label* label, source_location location)
2689 : Statement(STATEMENT_BREAK_OR_CONTINUE, location),
2690 label_(label), is_break_(is_break)
2695 { return this->is_break_; }
2699 do_traverse(Traverse*)
2700 { return TRAVERSE_CONTINUE; }
2703 do_may_fall_through() const
2707 do_get_tree(Translate_context*)
2708 { return this->label_->get_goto(this->location()); }
2711 // The label that this branches to.
2712 Unnamed_label* label_;
2713 // True if this is "break", false if it is "continue".
2717 // Make a break statement.
2720 Statement::make_break_statement(Unnamed_label* label, source_location location)
2722 return new Bc_statement(true, label, location);
2725 // Make a continue statement.
2728 Statement::make_continue_statement(Unnamed_label* label,
2729 source_location location)
2731 return new Bc_statement(false, label, location);
2734 // A goto statement.
2736 class Goto_statement : public Statement
2739 Goto_statement(Label* label, source_location location)
2740 : Statement(STATEMENT_GOTO, location),
2746 do_traverse(Traverse*)
2747 { return TRAVERSE_CONTINUE; }
2750 do_check_types(Gogo*);
2753 do_may_fall_through() const
2757 do_get_tree(Translate_context*);
2763 // Check types for a label. There aren't any types per se, but we use
2764 // this to give an error if the label was never defined.
2767 Goto_statement::do_check_types(Gogo*)
2769 if (!this->label_->is_defined())
2771 error_at(this->location(), "reference to undefined label %qs",
2772 Gogo::message_name(this->label_->name()).c_str());
2773 this->set_is_error();
2777 // Return the tree for the goto statement.
2780 Goto_statement::do_get_tree(Translate_context*)
2782 return this->build_stmt_1(GOTO_EXPR, this->label_->get_decl());
2785 // Make a goto statement.
2788 Statement::make_goto_statement(Label* label, source_location location)
2790 return new Goto_statement(label, location);
2793 // A goto statement to an unnamed label.
2795 class Goto_unnamed_statement : public Statement
2798 Goto_unnamed_statement(Unnamed_label* label, source_location location)
2799 : Statement(STATEMENT_GOTO_UNNAMED, location),
2805 do_traverse(Traverse*)
2806 { return TRAVERSE_CONTINUE; }
2809 do_may_fall_through() const
2813 do_get_tree(Translate_context*)
2814 { return this->label_->get_goto(this->location()); }
2817 Unnamed_label* label_;
2820 // Make a goto statement to an unnamed label.
2823 Statement::make_goto_unnamed_statement(Unnamed_label* label,
2824 source_location location)
2826 return new Goto_unnamed_statement(label, location);
2829 // Class Label_statement.
2834 Label_statement::do_traverse(Traverse*)
2836 return TRAVERSE_CONTINUE;
2839 // Return a tree defining this label.
2842 Label_statement::do_get_tree(Translate_context*)
2844 return this->build_stmt_1(LABEL_EXPR, this->label_->get_decl());
2847 // Make a label statement.
2850 Statement::make_label_statement(Label* label, source_location location)
2852 return new Label_statement(label, location);
2855 // An unnamed label statement.
2857 class Unnamed_label_statement : public Statement
2860 Unnamed_label_statement(Unnamed_label* label)
2861 : Statement(STATEMENT_UNNAMED_LABEL, label->location()),
2867 do_traverse(Traverse*)
2868 { return TRAVERSE_CONTINUE; }
2871 do_get_tree(Translate_context*)
2872 { return this->label_->get_definition(); }
2876 Unnamed_label* label_;
2879 // Make an unnamed label statement.
2882 Statement::make_unnamed_label_statement(Unnamed_label* label)
2884 return new Unnamed_label_statement(label);
2889 class If_statement : public Statement
2892 If_statement(Expression* cond, Block* then_block, Block* else_block,
2893 source_location location)
2894 : Statement(STATEMENT_IF, location),
2895 cond_(cond), then_block_(then_block), else_block_(else_block)
2900 do_traverse(Traverse*);
2903 do_determine_types();
2906 do_check_types(Gogo*);
2909 do_may_fall_through() const;
2912 do_get_tree(Translate_context*);
2923 If_statement::do_traverse(Traverse* traverse)
2925 if (this->cond_ != NULL)
2927 if (this->traverse_expression(traverse, &this->cond_) == TRAVERSE_EXIT)
2928 return TRAVERSE_EXIT;
2930 if (this->then_block_->traverse(traverse) == TRAVERSE_EXIT)
2931 return TRAVERSE_EXIT;
2932 if (this->else_block_ != NULL)
2934 if (this->else_block_->traverse(traverse) == TRAVERSE_EXIT)
2935 return TRAVERSE_EXIT;
2937 return TRAVERSE_CONTINUE;
2941 If_statement::do_determine_types()
2943 if (this->cond_ != NULL)
2945 Type_context context(Type::lookup_bool_type(), false);
2946 this->cond_->determine_type(&context);
2948 this->then_block_->determine_types();
2949 if (this->else_block_ != NULL)
2950 this->else_block_->determine_types();
2956 If_statement::do_check_types(Gogo*)
2958 if (this->cond_ != NULL)
2960 Type* type = this->cond_->type();
2961 if (type->is_error_type())
2962 this->set_is_error();
2963 else if (!type->is_boolean_type())
2964 this->report_error(_("expected boolean expression"));
2968 // Whether the overall statement may fall through.
2971 If_statement::do_may_fall_through() const
2973 return (this->else_block_ == NULL
2974 || this->then_block_->may_fall_through()
2975 || this->else_block_->may_fall_through());
2981 If_statement::do_get_tree(Translate_context* context)
2983 gcc_assert(this->cond_ == NULL || this->cond_->type()->is_boolean_type());
2984 tree ret = build3(COND_EXPR, void_type_node,
2985 (this->cond_ == NULL
2987 : this->cond_->get_tree(context)),
2988 this->then_block_->get_tree(context),
2989 (this->else_block_ == NULL
2991 : this->else_block_->get_tree(context)));
2992 SET_EXPR_LOCATION(ret, this->location());
2996 // Make an if statement.
2999 Statement::make_if_statement(Expression* cond, Block* then_block,
3000 Block* else_block, source_location location)
3002 return new If_statement(cond, then_block, else_block, location);
3005 // Class Case_clauses::Case_clause.
3010 Case_clauses::Case_clause::traverse(Traverse* traverse)
3012 if (this->cases_ != NULL
3013 && (traverse->traverse_mask() & Traverse::traverse_expressions) != 0)
3015 if (this->cases_->traverse(traverse) == TRAVERSE_EXIT)
3016 return TRAVERSE_EXIT;
3018 if (this->statements_ != NULL)
3020 if (this->statements_->traverse(traverse) == TRAVERSE_EXIT)
3021 return TRAVERSE_EXIT;
3023 return TRAVERSE_CONTINUE;
3026 // Check whether all the case expressions are integer constants.
3029 Case_clauses::Case_clause::is_constant() const
3031 if (this->cases_ != NULL)
3033 for (Expression_list::const_iterator p = this->cases_->begin();
3034 p != this->cases_->end();
3036 if (!(*p)->is_constant() || (*p)->type()->integer_type() == NULL)
3042 // Lower a case clause for a nonconstant switch. VAL_TEMP is the
3043 // value we are switching on; it may be NULL. If START_LABEL is not
3044 // NULL, it goes at the start of the statements, after the condition
3045 // test. We branch to FINISH_LABEL at the end of the statements.
3048 Case_clauses::Case_clause::lower(Block* b, Temporary_statement* val_temp,
3049 Unnamed_label* start_label,
3050 Unnamed_label* finish_label) const
3052 source_location loc = this->location_;
3053 Unnamed_label* next_case_label;
3054 if (this->cases_ == NULL || this->cases_->empty())
3056 gcc_assert(this->is_default_);
3057 next_case_label = NULL;
3061 Expression* cond = NULL;
3063 for (Expression_list::const_iterator p = this->cases_->begin();
3064 p != this->cases_->end();
3067 Expression* this_cond;
3068 if (val_temp == NULL)
3072 Expression* ref = Expression::make_temporary_reference(val_temp,
3074 this_cond = Expression::make_binary(OPERATOR_EQEQ, ref, *p, loc);
3080 cond = Expression::make_binary(OPERATOR_OROR, cond, this_cond, loc);
3083 Block* then_block = new Block(b, loc);
3084 next_case_label = new Unnamed_label(UNKNOWN_LOCATION);
3085 Statement* s = Statement::make_goto_unnamed_statement(next_case_label,
3087 then_block->add_statement(s);
3089 // if !COND { goto NEXT_CASE_LABEL }
3090 cond = Expression::make_unary(OPERATOR_NOT, cond, loc);
3091 s = Statement::make_if_statement(cond, then_block, NULL, loc);
3092 b->add_statement(s);
3095 if (start_label != NULL)
3096 b->add_statement(Statement::make_unnamed_label_statement(start_label));
3098 if (this->statements_ != NULL)
3099 b->add_statement(Statement::make_block_statement(this->statements_, loc));
3101 Statement* s = Statement::make_goto_unnamed_statement(finish_label, loc);
3102 b->add_statement(s);
3104 if (next_case_label != NULL)
3105 b->add_statement(Statement::make_unnamed_label_statement(next_case_label));
3111 Case_clauses::Case_clause::determine_types(Type* type)
3113 if (this->cases_ != NULL)
3115 Type_context case_context(type, false);
3116 for (Expression_list::iterator p = this->cases_->begin();
3117 p != this->cases_->end();
3119 (*p)->determine_type(&case_context);
3121 if (this->statements_ != NULL)
3122 this->statements_->determine_types();
3125 // Check types. Returns false if there was an error.
3128 Case_clauses::Case_clause::check_types(Type* type)
3130 if (this->cases_ != NULL)
3132 for (Expression_list::iterator p = this->cases_->begin();
3133 p != this->cases_->end();
3136 if (!Type::are_assignable(type, (*p)->type(), NULL)
3137 && !Type::are_assignable((*p)->type(), type, NULL))
3139 error_at((*p)->location(),
3140 "type mismatch between switch value and case clause");
3148 // Return true if this clause may fall through to the following
3149 // statements. Note that this is not the same as whether the case
3150 // uses the "fallthrough" keyword.
3153 Case_clauses::Case_clause::may_fall_through() const
3155 if (this->statements_ == NULL)
3157 return this->statements_->may_fall_through();
3160 // Build up the body of a SWITCH_EXPR.
3163 Case_clauses::Case_clause::get_constant_tree(Translate_context* context,
3164 Unnamed_label* break_label,
3165 Case_constants* case_constants,
3166 tree* stmt_list) const
3168 if (this->cases_ != NULL)
3170 for (Expression_list::const_iterator p = this->cases_->begin();
3171 p != this->cases_->end();
3177 if (!(*p)->integer_constant_value(true, ival, &itype))
3179 gcc_assert(itype != NULL);
3180 tree type_tree = itype->get_tree(context->gogo());
3181 tree val = Expression::integer_constant_tree(ival, type_tree);
3184 if (val != error_mark_node)
3186 gcc_assert(TREE_CODE(val) == INTEGER_CST);
3188 std::pair<Case_constants::iterator, bool> ins =
3189 case_constants->insert(val);
3192 // Value was already present.
3193 warning_at(this->location_, 0,
3194 "duplicate case value will never match");
3198 tree label = create_artificial_label(this->location_);
3199 append_to_statement_list(build3(CASE_LABEL_EXPR, void_type_node,
3200 val, NULL_TREE, label),
3206 if (this->is_default_)
3208 tree label = create_artificial_label(this->location_);
3209 append_to_statement_list(build3(CASE_LABEL_EXPR, void_type_node,
3210 NULL_TREE, NULL_TREE, label),
3214 if (this->statements_ != NULL)
3216 tree block_tree = this->statements_->get_tree(context);
3217 if (block_tree != error_mark_node)
3218 append_to_statement_list(block_tree, stmt_list);
3221 if (!this->is_fallthrough_)
3222 append_to_statement_list(break_label->get_goto(this->location_), stmt_list);
3225 // Class Case_clauses.
3230 Case_clauses::traverse(Traverse* traverse)
3232 for (Clauses::iterator p = this->clauses_.begin();
3233 p != this->clauses_.end();
3236 if (p->traverse(traverse) == TRAVERSE_EXIT)
3237 return TRAVERSE_EXIT;
3239 return TRAVERSE_CONTINUE;
3242 // Check whether all the case expressions are constant.
3245 Case_clauses::is_constant() const
3247 for (Clauses::const_iterator p = this->clauses_.begin();
3248 p != this->clauses_.end();
3250 if (!p->is_constant())
3255 // Lower case clauses for a nonconstant switch.
3258 Case_clauses::lower(Block* b, Temporary_statement* val_temp,
3259 Unnamed_label* break_label) const
3261 // The default case.
3262 const Case_clause* default_case = NULL;
3264 // The label for the fallthrough of the previous case.
3265 Unnamed_label* last_fallthrough_label = NULL;
3267 // The label for the start of the default case. This is used if the
3268 // case before the default case falls through.
3269 Unnamed_label* default_start_label = NULL;
3271 // The label for the end of the default case. This normally winds
3272 // up as BREAK_LABEL, but it will be different if the default case
3274 Unnamed_label* default_finish_label = NULL;
3276 for (Clauses::const_iterator p = this->clauses_.begin();
3277 p != this->clauses_.end();
3280 // The label to use for the start of the statements for this
3281 // case. This is NULL unless the previous case falls through.
3282 Unnamed_label* start_label = last_fallthrough_label;
3284 // The label to jump to after the end of the statements for this
3286 Unnamed_label* finish_label = break_label;
3288 last_fallthrough_label = NULL;
3289 if (p->is_fallthrough() && p + 1 != this->clauses_.end())
3291 finish_label = new Unnamed_label(p->location());
3292 last_fallthrough_label = finish_label;
3295 if (!p->is_default())
3296 p->lower(b, val_temp, start_label, finish_label);
3299 // We have to move the default case to the end, so that we
3300 // only use it if all the other tests fail.
3302 default_start_label = start_label;
3303 default_finish_label = finish_label;
3307 if (default_case != NULL)
3308 default_case->lower(b, val_temp, default_start_label,
3309 default_finish_label);
3316 Case_clauses::determine_types(Type* type)
3318 for (Clauses::iterator p = this->clauses_.begin();
3319 p != this->clauses_.end();
3321 p->determine_types(type);
3324 // Check types. Returns false if there was an error.
3327 Case_clauses::check_types(Type* type)
3330 for (Clauses::iterator p = this->clauses_.begin();
3331 p != this->clauses_.end();
3334 if (!p->check_types(type))
3340 // Return true if these clauses may fall through to the statements
3341 // following the switch statement.
3344 Case_clauses::may_fall_through() const
3346 bool found_default = false;
3347 for (Clauses::const_iterator p = this->clauses_.begin();
3348 p != this->clauses_.end();
3351 if (p->may_fall_through() && !p->is_fallthrough())
3353 if (p->is_default())
3354 found_default = true;
3356 return !found_default;
3359 // Return a tree when all case expressions are constants.
3362 Case_clauses::get_constant_tree(Translate_context* context,
3363 Unnamed_label* break_label) const
3365 Case_constants case_constants;
3366 tree stmt_list = NULL_TREE;
3367 for (Clauses::const_iterator p = this->clauses_.begin();
3368 p != this->clauses_.end();
3370 p->get_constant_tree(context, break_label, &case_constants,
3375 // A constant switch statement. A Switch_statement is lowered to this
3376 // when all the cases are constants.
3378 class Constant_switch_statement : public Statement
3381 Constant_switch_statement(Expression* val, Case_clauses* clauses,
3382 Unnamed_label* break_label,
3383 source_location location)
3384 : Statement(STATEMENT_CONSTANT_SWITCH, location),
3385 val_(val), clauses_(clauses), break_label_(break_label)
3390 do_traverse(Traverse*);
3393 do_determine_types();
3396 do_check_types(Gogo*);
3399 do_may_fall_through() const;
3402 do_get_tree(Translate_context*);
3405 // The value to switch on.
3407 // The case clauses.
3408 Case_clauses* clauses_;
3409 // The break label, if needed.
3410 Unnamed_label* break_label_;
3416 Constant_switch_statement::do_traverse(Traverse* traverse)
3418 if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT)
3419 return TRAVERSE_EXIT;
3420 return this->clauses_->traverse(traverse);
3426 Constant_switch_statement::do_determine_types()
3428 this->val_->determine_type_no_context();
3429 this->clauses_->determine_types(this->val_->type());
3435 Constant_switch_statement::do_check_types(Gogo*)
3437 if (!this->clauses_->check_types(this->val_->type()))
3438 this->set_is_error();
3441 // Return whether this switch may fall through.
3444 Constant_switch_statement::do_may_fall_through() const
3446 if (this->clauses_ == NULL)
3449 // If we have a break label, then some case needed it. That implies
3450 // that the switch statement as a whole can fall through.
3451 if (this->break_label_ != NULL)
3454 return this->clauses_->may_fall_through();
3457 // Convert to GENERIC.
3460 Constant_switch_statement::do_get_tree(Translate_context* context)
3462 tree switch_val_tree = this->val_->get_tree(context);
3464 Unnamed_label* break_label = this->break_label_;
3465 if (break_label == NULL)
3466 break_label = new Unnamed_label(this->location());
3468 tree stmt_list = NULL_TREE;
3469 tree s = build3(SWITCH_EXPR, void_type_node, switch_val_tree,
3470 this->clauses_->get_constant_tree(context, break_label),
3472 SET_EXPR_LOCATION(s, this->location());
3473 append_to_statement_list(s, &stmt_list);
3475 append_to_statement_list(break_label->get_definition(), &stmt_list);
3480 // Class Switch_statement.
3485 Switch_statement::do_traverse(Traverse* traverse)
3487 if (this->val_ != NULL)
3489 if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT)
3490 return TRAVERSE_EXIT;
3492 return this->clauses_->traverse(traverse);
3495 // Lower a Switch_statement to a Constant_switch_statement or a series
3496 // of if statements.
3499 Switch_statement::do_lower(Gogo*, Block* enclosing)
3501 source_location loc = this->location();
3503 if (this->val_ != NULL
3504 && (this->val_->is_error_expression()
3505 || this->val_->type()->is_error_type()))
3506 return Statement::make_error_statement(loc);
3508 if (this->val_ != NULL
3509 && this->val_->type()->integer_type() != NULL
3510 && !this->clauses_->empty()
3511 && this->clauses_->is_constant())
3512 return new Constant_switch_statement(this->val_, this->clauses_,
3513 this->break_label_, loc);
3515 Block* b = new Block(enclosing, loc);
3517 if (this->clauses_->empty())
3519 Expression* val = this->val_;
3521 val = Expression::make_boolean(true, loc);
3522 return Statement::make_statement(val);
3525 Temporary_statement* val_temp;
3526 if (this->val_ == NULL)
3530 // var val_temp VAL_TYPE = VAL
3531 val_temp = Statement::make_temporary(NULL, this->val_, loc);
3532 b->add_statement(val_temp);
3535 this->clauses_->lower(b, val_temp, this->break_label());
3537 Statement* s = Statement::make_unnamed_label_statement(this->break_label_);
3538 b->add_statement(s);
3540 return Statement::make_block_statement(b, loc);
3543 // Return the break label for this switch statement, creating it if
3547 Switch_statement::break_label()
3549 if (this->break_label_ == NULL)
3550 this->break_label_ = new Unnamed_label(this->location());
3551 return this->break_label_;
3554 // Make a switch statement.
3557 Statement::make_switch_statement(Expression* val, source_location location)
3559 return new Switch_statement(val, location);
3562 // Class Type_case_clauses::Type_case_clause.
3567 Type_case_clauses::Type_case_clause::traverse(Traverse* traverse)
3569 if (!this->is_default_
3570 && ((traverse->traverse_mask()
3571 & (Traverse::traverse_types | Traverse::traverse_expressions)) != 0)
3572 && Type::traverse(this->type_, traverse) == TRAVERSE_EXIT)
3573 return TRAVERSE_EXIT;
3574 if (this->statements_ != NULL)
3575 return this->statements_->traverse(traverse);
3576 return TRAVERSE_CONTINUE;
3579 // Lower one clause in a type switch. Add statements to the block B.
3580 // The type descriptor we are switching on is in DESCRIPTOR_TEMP.
3581 // BREAK_LABEL is the label at the end of the type switch.
3582 // *STMTS_LABEL, if not NULL, is a label to put at the start of the
3586 Type_case_clauses::Type_case_clause::lower(Block* b,
3587 Temporary_statement* descriptor_temp,
3588 Unnamed_label* break_label,
3589 Unnamed_label** stmts_label) const
3591 source_location loc = this->location_;
3593 Unnamed_label* next_case_label = NULL;
3594 if (!this->is_default_)
3596 Type* type = this->type_;
3599 // The language permits case nil, which is of course a constant
3600 // rather than a type. It will appear here as an invalid
3602 if (type->is_nil_constant_as_type())
3605 Expression::make_temporary_reference(descriptor_temp, loc);
3606 cond = Expression::make_binary(OPERATOR_EQEQ, ref,
3607 Expression::make_nil(loc),
3613 if (type->interface_type() == NULL)
3615 // func ifacetypeeq(*descriptor, *descriptor) bool
3616 static Named_object* ifacetypeeq;
3617 if (ifacetypeeq == NULL)
3619 const source_location bloc = BUILTINS_LOCATION;
3620 Typed_identifier_list* param_types =
3621 new Typed_identifier_list();
3622 Type* descriptor_type = Type::make_type_descriptor_ptr_type();
3623 param_types->push_back(Typed_identifier("a", descriptor_type,
3625 param_types->push_back(Typed_identifier("b", descriptor_type,
3627 Typed_identifier_list* ret_types =
3628 new Typed_identifier_list();
3629 Type* bool_type = Type::lookup_bool_type();
3630 ret_types->push_back(Typed_identifier("", bool_type, bloc));
3631 Function_type* fntype = Type::make_function_type(NULL,
3636 Named_object::make_function_declaration("ifacetypeeq", NULL,
3638 const char* n = "runtime.ifacetypeeq";
3639 ifacetypeeq->func_declaration_value()->set_asm_name(n);
3642 // ifacetypeeq(descriptor_temp, DESCRIPTOR)
3643 func = Expression::make_func_reference(ifacetypeeq, NULL, loc);
3647 // func ifaceI2Tp(*descriptor, *descriptor) bool
3648 static Named_object* ifaceI2Tp;
3649 if (ifaceI2Tp == NULL)
3651 const source_location bloc = BUILTINS_LOCATION;
3652 Typed_identifier_list* param_types =
3653 new Typed_identifier_list();
3654 Type* descriptor_type = Type::make_type_descriptor_ptr_type();
3655 param_types->push_back(Typed_identifier("a", descriptor_type,
3657 param_types->push_back(Typed_identifier("b", descriptor_type,
3659 Typed_identifier_list* ret_types =
3660 new Typed_identifier_list();
3661 Type* bool_type = Type::lookup_bool_type();
3662 ret_types->push_back(Typed_identifier("", bool_type, bloc));
3663 Function_type* fntype = Type::make_function_type(NULL,
3668 Named_object::make_function_declaration("ifaceI2Tp", NULL,
3670 const char* n = "runtime.ifaceI2Tp";
3671 ifaceI2Tp->func_declaration_value()->set_asm_name(n);
3674 // ifaceI2Tp(descriptor_temp, DESCRIPTOR)
3675 func = Expression::make_func_reference(ifaceI2Tp, NULL, loc);
3677 Expression_list* params = new Expression_list();
3678 params->push_back(Expression::make_type_descriptor(type, loc));
3680 Expression::make_temporary_reference(descriptor_temp, loc);
3681 params->push_back(ref);
3682 cond = Expression::make_call(func, params, false, loc);
3685 Unnamed_label* dest;
3686 if (!this->is_fallthrough_)
3688 // if !COND { goto NEXT_CASE_LABEL }
3689 next_case_label = new Unnamed_label(UNKNOWN_LOCATION);
3690 dest = next_case_label;
3691 cond = Expression::make_unary(OPERATOR_NOT, cond, loc);
3695 // if COND { goto STMTS_LABEL }
3696 gcc_assert(stmts_label != NULL);
3697 if (*stmts_label == NULL)
3698 *stmts_label = new Unnamed_label(UNKNOWN_LOCATION);
3699 dest = *stmts_label;
3701 Block* then_block = new Block(b, loc);
3702 Statement* s = Statement::make_goto_unnamed_statement(dest, loc);
3703 then_block->add_statement(s);
3704 s = Statement::make_if_statement(cond, then_block, NULL, loc);
3705 b->add_statement(s);
3708 if (this->statements_ != NULL
3709 || (!this->is_fallthrough_
3710 && stmts_label != NULL
3711 && *stmts_label != NULL))
3713 gcc_assert(!this->is_fallthrough_);
3714 if (stmts_label != NULL && *stmts_label != NULL)
3716 gcc_assert(!this->is_default_);
3717 if (this->statements_ != NULL)
3718 (*stmts_label)->set_location(this->statements_->start_location());
3719 Statement* s = Statement::make_unnamed_label_statement(*stmts_label);
3720 b->add_statement(s);
3721 *stmts_label = NULL;
3723 if (this->statements_ != NULL)
3724 b->add_statement(Statement::make_block_statement(this->statements_,
3728 if (this->is_fallthrough_)
3729 gcc_assert(next_case_label == NULL);
3732 source_location gloc = (this->statements_ == NULL
3734 : this->statements_->end_location());
3735 b->add_statement(Statement::make_goto_unnamed_statement(break_label,
3737 if (next_case_label != NULL)
3740 Statement::make_unnamed_label_statement(next_case_label);
3741 b->add_statement(s);
3746 // Class Type_case_clauses.
3751 Type_case_clauses::traverse(Traverse* traverse)
3753 for (Type_clauses::iterator p = this->clauses_.begin();
3754 p != this->clauses_.end();
3757 if (p->traverse(traverse) == TRAVERSE_EXIT)
3758 return TRAVERSE_EXIT;
3760 return TRAVERSE_CONTINUE;
3763 // Check for duplicate types.
3766 Type_case_clauses::check_duplicates() const
3768 typedef Unordered_set_hash(const Type*, Type_hash_identical,
3769 Type_identical) Types_seen;
3770 Types_seen types_seen;
3771 for (Type_clauses::const_iterator p = this->clauses_.begin();
3772 p != this->clauses_.end();
3775 Type* t = p->type();
3778 if (t->is_nil_constant_as_type())
3779 t = Type::make_nil_type();
3780 std::pair<Types_seen::iterator, bool> ins = types_seen.insert(t);
3782 error_at(p->location(), "duplicate type in switch");
3786 // Lower the clauses in a type switch. Add statements to the block B.
3787 // The type descriptor we are switching on is in DESCRIPTOR_TEMP.
3788 // BREAK_LABEL is the label at the end of the type switch.
3791 Type_case_clauses::lower(Block* b, Temporary_statement* descriptor_temp,
3792 Unnamed_label* break_label) const
3794 const Type_case_clause* default_case = NULL;
3796 Unnamed_label* stmts_label = NULL;
3797 for (Type_clauses::const_iterator p = this->clauses_.begin();
3798 p != this->clauses_.end();
3801 if (!p->is_default())
3802 p->lower(b, descriptor_temp, break_label, &stmts_label);
3805 // We are generating a series of tests, which means that we
3806 // need to move the default case to the end.
3810 gcc_assert(stmts_label == NULL);
3812 if (default_case != NULL)
3813 default_case->lower(b, descriptor_temp, break_label, NULL);
3816 // Class Type_switch_statement.
3821 Type_switch_statement::do_traverse(Traverse* traverse)
3823 if (this->var_ == NULL)
3825 if (this->traverse_expression(traverse, &this->expr_) == TRAVERSE_EXIT)
3826 return TRAVERSE_EXIT;
3828 if (this->clauses_ != NULL)
3829 return this->clauses_->traverse(traverse);
3830 return TRAVERSE_CONTINUE;
3833 // Lower a type switch statement to a series of if statements. The gc
3834 // compiler is able to generate a table in some cases. However, that
3835 // does not work for us because we may have type descriptors in
3836 // different shared libraries, so we can't compare them with simple
3837 // equality testing.
3840 Type_switch_statement::do_lower(Gogo*, Block* enclosing)
3842 const source_location loc = this->location();
3844 if (this->clauses_ != NULL)
3845 this->clauses_->check_duplicates();
3847 Block* b = new Block(enclosing, loc);
3849 Type* val_type = (this->var_ != NULL
3850 ? this->var_->var_value()->type()
3851 : this->expr_->type());
3853 // var descriptor_temp DESCRIPTOR_TYPE
3854 Type* descriptor_type = Type::make_type_descriptor_ptr_type();
3855 Temporary_statement* descriptor_temp =
3856 Statement::make_temporary(descriptor_type, NULL, loc);
3857 b->add_statement(descriptor_temp);
3859 if (val_type->interface_type() == NULL)
3861 // Doing a type switch on a non-interface type. Should we issue
3862 // a warning for this case?
3863 // descriptor_temp = DESCRIPTOR
3864 Expression* lhs = Expression::make_temporary_reference(descriptor_temp,
3866 Expression* rhs = Expression::make_type_descriptor(val_type, loc);
3867 Statement* s = Statement::make_assignment(lhs, rhs, loc);
3868 b->add_statement(s);
3872 const source_location bloc = BUILTINS_LOCATION;
3874 // func {efacetype,ifacetype}(*interface) *descriptor
3875 // FIXME: This should be inlined.
3876 Typed_identifier_list* param_types = new Typed_identifier_list();
3877 param_types->push_back(Typed_identifier("i", val_type, bloc));
3878 Typed_identifier_list* ret_types = new Typed_identifier_list();
3879 ret_types->push_back(Typed_identifier("", descriptor_type, bloc));
3880 Function_type* fntype = Type::make_function_type(NULL, param_types,
3882 bool is_empty = val_type->interface_type()->is_empty();
3883 const char* fnname = is_empty ? "efacetype" : "ifacetype";
3885 Named_object::make_function_declaration(fnname, NULL, fntype, bloc);
3886 const char* asm_name = (is_empty
3887 ? "runtime.efacetype"
3888 : "runtime.ifacetype");
3889 fn->func_declaration_value()->set_asm_name(asm_name);
3891 // descriptor_temp = ifacetype(val_temp)
3892 Expression* func = Expression::make_func_reference(fn, NULL, loc);
3893 Expression_list* params = new Expression_list();
3895 if (this->var_ == NULL)
3898 ref = Expression::make_var_reference(this->var_, loc);
3899 params->push_back(ref);
3900 Expression* call = Expression::make_call(func, params, false, loc);
3901 Expression* lhs = Expression::make_temporary_reference(descriptor_temp,
3903 Statement* s = Statement::make_assignment(lhs, call, loc);
3904 b->add_statement(s);
3907 if (this->clauses_ != NULL)
3908 this->clauses_->lower(b, descriptor_temp, this->break_label());
3910 Statement* s = Statement::make_unnamed_label_statement(this->break_label_);
3911 b->add_statement(s);
3913 return Statement::make_block_statement(b, loc);
3916 // Return the break label for this type switch statement, creating it
3920 Type_switch_statement::break_label()
3922 if (this->break_label_ == NULL)
3923 this->break_label_ = new Unnamed_label(this->location());
3924 return this->break_label_;
3927 // Make a type switch statement.
3929 Type_switch_statement*
3930 Statement::make_type_switch_statement(Named_object* var, Expression* expr,
3931 source_location location)
3933 return new Type_switch_statement(var, expr, location);
3936 // Class Select_clauses::Select_clause.
3941 Select_clauses::Select_clause::traverse(Traverse* traverse)
3943 if (!this->is_lowered_
3944 && (traverse->traverse_mask() & Traverse::traverse_expressions) != 0)
3946 if (this->channel_ != NULL)
3948 if (Expression::traverse(&this->channel_, traverse) == TRAVERSE_EXIT)
3949 return TRAVERSE_EXIT;
3951 if (this->val_ != NULL)
3953 if (Expression::traverse(&this->val_, traverse) == TRAVERSE_EXIT)
3954 return TRAVERSE_EXIT;
3957 if (this->statements_ != NULL)
3959 if (this->statements_->traverse(traverse) == TRAVERSE_EXIT)
3960 return TRAVERSE_EXIT;
3962 return TRAVERSE_CONTINUE;
3965 // Lowering. Here we pull out the channel and the send values, to
3966 // enforce the order of evaluation. We also add explicit send and
3967 // receive statements to the clauses.
3970 Select_clauses::Select_clause::lower(Block* b)
3972 if (this->is_default_)
3974 gcc_assert(this->channel_ == NULL && this->val_ == NULL);
3975 this->is_lowered_ = true;
3979 source_location loc = this->location_;
3981 // Evaluate the channel before the select statement.
3982 Temporary_statement* channel_temp = Statement::make_temporary(NULL,
3985 b->add_statement(channel_temp);
3986 this->channel_ = Expression::make_temporary_reference(channel_temp, loc);
3988 // If this is a send clause, evaluate the value to send before the
3989 // select statement.
3990 Temporary_statement* val_temp = NULL;
3993 val_temp = Statement::make_temporary(NULL, this->val_, loc);
3994 b->add_statement(val_temp);
3997 // Add the send or receive before the rest of the statements if any.
3998 Block *init = new Block(b, loc);
3999 Expression* ref = Expression::make_temporary_reference(channel_temp, loc);
4002 Expression* ref2 = Expression::make_temporary_reference(val_temp, loc);
4003 Send_expression* send = Expression::make_send(ref, ref2, loc);
4004 send->discarding_value();
4005 send->set_for_select();
4006 init->add_statement(Statement::make_statement(send));
4010 Receive_expression* recv = Expression::make_receive(ref, loc);
4011 recv->set_for_select();
4012 if (this->val_ != NULL)
4014 gcc_assert(this->var_ == NULL);
4015 init->add_statement(Statement::make_assignment(this->val_, recv,
4018 else if (this->var_ != NULL)
4020 this->var_->var_value()->set_init(recv);
4021 this->var_->var_value()->clear_type_from_chan_element();
4025 recv->discarding_value();
4026 init->add_statement(Statement::make_statement(recv));
4030 if (this->statements_ != NULL)
4031 init->add_statement(Statement::make_block_statement(this->statements_,
4034 this->statements_ = init;
4036 // Now all references should be handled through the statements, not
4038 this->is_lowered_ = true;
4046 Select_clauses::Select_clause::determine_types()
4048 gcc_assert(this->is_lowered_);
4049 if (this->statements_ != NULL)
4050 this->statements_->determine_types();
4053 // Whether this clause may fall through to the statement which follows
4054 // the overall select statement.
4057 Select_clauses::Select_clause::may_fall_through() const
4059 if (this->statements_ == NULL)
4061 return this->statements_->may_fall_through();
4064 // Return a tree for the statements to execute.
4067 Select_clauses::Select_clause::get_statements_tree(Translate_context* context)
4069 if (this->statements_ == NULL)
4071 return this->statements_->get_tree(context);
4074 // Class Select_clauses.
4079 Select_clauses::traverse(Traverse* traverse)
4081 for (Clauses::iterator p = this->clauses_.begin();
4082 p != this->clauses_.end();
4085 if (p->traverse(traverse) == TRAVERSE_EXIT)
4086 return TRAVERSE_EXIT;
4088 return TRAVERSE_CONTINUE;
4091 // Lowering. Here we pull out the channel and the send values, to
4092 // enforce the order of evaluation. We also add explicit send and
4093 // receive statements to the clauses.
4096 Select_clauses::lower(Block* b)
4098 for (Clauses::iterator p = this->clauses_.begin();
4099 p != this->clauses_.end();
4107 Select_clauses::determine_types()
4109 for (Clauses::iterator p = this->clauses_.begin();
4110 p != this->clauses_.end();
4112 p->determine_types();
4115 // Return whether these select clauses fall through to the statement
4116 // following the overall select statement.
4119 Select_clauses::may_fall_through() const
4121 for (Clauses::const_iterator p = this->clauses_.begin();
4122 p != this->clauses_.end();
4124 if (p->may_fall_through())
4129 // Return a tree. We build a call to
4130 // size_t __go_select(size_t count, _Bool has_default,
4131 // channel* channels, _Bool* is_send)
4133 // There are COUNT entries in the CHANNELS and IS_SEND arrays. The
4134 // value in the IS_SEND array is true for send, false for receive.
4135 // __go_select returns an integer from 0 to COUNT, inclusive. A
4136 // return of 0 means that the default case should be run; this only
4137 // happens if HAS_DEFAULT is non-zero. Otherwise the number indicates
4140 // FIXME: This doesn't handle channels which send interface types
4141 // where the receiver has a static type which matches that interface.
4144 Select_clauses::get_tree(Translate_context* context,
4145 Unnamed_label *break_label,
4146 source_location location)
4148 size_t count = this->clauses_.size();
4149 VEC(constructor_elt, gc)* chan_init = VEC_alloc(constructor_elt, gc, count);
4150 VEC(constructor_elt, gc)* is_send_init = VEC_alloc(constructor_elt, gc,
4152 Select_clause* default_clause = NULL;
4153 tree final_stmt_list = NULL_TREE;
4154 tree channel_type_tree = NULL_TREE;
4157 for (Clauses::iterator p = this->clauses_.begin();
4158 p != this->clauses_.end();
4161 if (p->is_default())
4163 default_clause = &*p;
4168 if (p->channel()->type()->channel_type() == NULL)
4170 // We should have given an error in the send or receive
4171 // statement we created via lowering.
4172 gcc_assert(saw_errors());
4173 return error_mark_node;
4176 tree channel_tree = p->channel()->get_tree(context);
4177 if (channel_tree == error_mark_node)
4178 return error_mark_node;
4179 channel_type_tree = TREE_TYPE(channel_tree);
4181 constructor_elt* elt = VEC_quick_push(constructor_elt, chan_init, NULL);
4182 elt->index = build_int_cstu(sizetype, i);
4183 elt->value = channel_tree;
4185 elt = VEC_quick_push(constructor_elt, is_send_init, NULL);
4186 elt->index = build_int_cstu(sizetype, i);
4187 elt->value = p->is_send() ? boolean_true_node : boolean_false_node;
4191 gcc_assert(i == count);
4193 if (i == 0 && default_clause != NULL)
4195 // There is only a default clause.
4196 gcc_assert(final_stmt_list == NULL_TREE);
4197 tree stmt_list = NULL_TREE;
4198 append_to_statement_list(default_clause->get_statements_tree(context),
4200 append_to_statement_list(break_label->get_definition(), &stmt_list);
4204 tree pointer_chan_type_tree = (channel_type_tree == NULL_TREE
4206 : build_pointer_type(channel_type_tree));
4208 tree pointer_boolean_type_tree = build_pointer_type(boolean_type_node);
4213 chans_arg = fold_convert_loc(location, pointer_chan_type_tree,
4215 is_sends_arg = fold_convert_loc(location, pointer_boolean_type_tree,
4220 tree index_type_tree = build_index_type(size_int(count - 1));
4221 tree chan_array_type_tree = build_array_type(channel_type_tree,
4223 tree chan_constructor = build_constructor(chan_array_type_tree,
4225 tree chan_var = create_tmp_var(chan_array_type_tree, "CHAN");
4226 DECL_IGNORED_P(chan_var) = 0;
4227 DECL_INITIAL(chan_var) = chan_constructor;
4228 DECL_SOURCE_LOCATION(chan_var) = location;
4229 TREE_ADDRESSABLE(chan_var) = 1;
4230 tree decl_expr = build1(DECL_EXPR, void_type_node, chan_var);
4231 SET_EXPR_LOCATION(decl_expr, location);
4232 append_to_statement_list(decl_expr, &final_stmt_list);
4234 tree is_send_array_type_tree = build_array_type(boolean_type_node,
4236 tree is_send_constructor = build_constructor(is_send_array_type_tree,
4238 tree is_send_var = create_tmp_var(is_send_array_type_tree, "ISSEND");
4239 DECL_IGNORED_P(is_send_var) = 0;
4240 DECL_INITIAL(is_send_var) = is_send_constructor;
4241 DECL_SOURCE_LOCATION(is_send_var) = location;
4242 TREE_ADDRESSABLE(is_send_var) = 1;
4243 decl_expr = build1(DECL_EXPR, void_type_node, is_send_var);
4244 SET_EXPR_LOCATION(decl_expr, location);
4245 append_to_statement_list(decl_expr, &final_stmt_list);
4247 chans_arg = fold_convert_loc(location, pointer_chan_type_tree,
4248 build_fold_addr_expr_loc(location,
4250 is_sends_arg = fold_convert_loc(location, pointer_boolean_type_tree,
4251 build_fold_addr_expr_loc(location,
4255 static tree select_fndecl;
4256 tree call = Gogo::call_builtin(&select_fndecl,
4264 (default_clause == NULL
4265 ? boolean_false_node
4266 : boolean_true_node),
4267 pointer_chan_type_tree,
4269 pointer_boolean_type_tree,
4271 if (call == error_mark_node)
4272 return error_mark_node;
4274 tree stmt_list = NULL_TREE;
4276 if (default_clause != NULL)
4277 this->add_clause_tree(context, 0, default_clause, break_label, &stmt_list);
4280 for (Clauses::iterator p = this->clauses_.begin();
4281 p != this->clauses_.end();
4284 if (!p->is_default())
4286 this->add_clause_tree(context, i, &*p, break_label, &stmt_list);
4291 append_to_statement_list(break_label->get_definition(), &stmt_list);
4293 tree switch_stmt = build3(SWITCH_EXPR, sizetype, call, stmt_list, NULL_TREE);
4294 SET_EXPR_LOCATION(switch_stmt, location);
4295 append_to_statement_list(switch_stmt, &final_stmt_list);
4297 return final_stmt_list;
4300 // Add the tree for CLAUSE to STMT_LIST.
4303 Select_clauses::add_clause_tree(Translate_context* context, int case_index,
4304 Select_clause* clause,
4305 Unnamed_label* bottom_label, tree* stmt_list)
4307 tree label = create_artificial_label(clause->location());
4308 append_to_statement_list(build3(CASE_LABEL_EXPR, void_type_node,
4309 build_int_cst(sizetype, case_index),
4312 append_to_statement_list(clause->get_statements_tree(context), stmt_list);
4313 tree g = bottom_label->get_goto(clause->statements() == NULL
4314 ? clause->location()
4315 : clause->statements()->end_location());
4316 append_to_statement_list(g, stmt_list);
4319 // Class Select_statement.
4321 // Return the break label for this switch statement, creating it if
4325 Select_statement::break_label()
4327 if (this->break_label_ == NULL)
4328 this->break_label_ = new Unnamed_label(this->location());
4329 return this->break_label_;
4332 // Lower a select statement. This will still return a select
4333 // statement, but it will be modified to implement the order of
4334 // evaluation rules, and to include the send and receive statements as
4335 // explicit statements in the clauses.
4338 Select_statement::do_lower(Gogo*, Block* enclosing)
4340 if (this->is_lowered_)
4342 Block* b = new Block(enclosing, this->location());
4343 this->clauses_->lower(b);
4344 this->is_lowered_ = true;
4345 b->add_statement(this);
4346 return Statement::make_block_statement(b, this->location());
4349 // Return the tree for a select statement.
4352 Select_statement::do_get_tree(Translate_context* context)
4354 return this->clauses_->get_tree(context, this->break_label(),
4358 // Make a select statement.
4361 Statement::make_select_statement(source_location location)
4363 return new Select_statement(location);
4366 // Class For_statement.
4371 For_statement::do_traverse(Traverse* traverse)
4373 if (this->init_ != NULL)
4375 if (this->init_->traverse(traverse) == TRAVERSE_EXIT)
4376 return TRAVERSE_EXIT;
4378 if (this->cond_ != NULL)
4380 if (this->traverse_expression(traverse, &this->cond_) == TRAVERSE_EXIT)
4381 return TRAVERSE_EXIT;
4383 if (this->post_ != NULL)
4385 if (this->post_->traverse(traverse) == TRAVERSE_EXIT)
4386 return TRAVERSE_EXIT;
4388 return this->statements_->traverse(traverse);
4391 // Lower a For_statement into if statements and gotos. Getting rid of
4392 // complex statements make it easier to handle garbage collection.
4395 For_statement::do_lower(Gogo*, Block* enclosing)
4398 source_location loc = this->location();
4400 Block* b = new Block(enclosing, this->location());
4401 if (this->init_ != NULL)
4403 s = Statement::make_block_statement(this->init_,
4404 this->init_->start_location());
4405 b->add_statement(s);
4408 Unnamed_label* entry = NULL;
4409 if (this->cond_ != NULL)
4411 entry = new Unnamed_label(this->location());
4412 b->add_statement(Statement::make_goto_unnamed_statement(entry, loc));
4415 Unnamed_label* top = new Unnamed_label(this->location());
4416 b->add_statement(Statement::make_unnamed_label_statement(top));
4418 s = Statement::make_block_statement(this->statements_,
4419 this->statements_->start_location());
4420 b->add_statement(s);
4422 source_location end_loc = this->statements_->end_location();
4424 Unnamed_label* cont = this->continue_label_;
4426 b->add_statement(Statement::make_unnamed_label_statement(cont));
4428 if (this->post_ != NULL)
4430 s = Statement::make_block_statement(this->post_,
4431 this->post_->start_location());
4432 b->add_statement(s);
4433 end_loc = this->post_->end_location();
4436 if (this->cond_ == NULL)
4437 b->add_statement(Statement::make_goto_unnamed_statement(top, end_loc));
4440 b->add_statement(Statement::make_unnamed_label_statement(entry));
4442 source_location cond_loc = this->cond_->location();
4443 Block* then_block = new Block(b, cond_loc);
4444 s = Statement::make_goto_unnamed_statement(top, cond_loc);
4445 then_block->add_statement(s);
4447 s = Statement::make_if_statement(this->cond_, then_block, NULL, cond_loc);
4448 b->add_statement(s);
4451 Unnamed_label* brk = this->break_label_;
4453 b->add_statement(Statement::make_unnamed_label_statement(brk));
4455 b->set_end_location(end_loc);
4457 return Statement::make_block_statement(b, loc);
4460 // Return the break label, creating it if necessary.
4463 For_statement::break_label()
4465 if (this->break_label_ == NULL)
4466 this->break_label_ = new Unnamed_label(this->location());
4467 return this->break_label_;
4470 // Return the continue LABEL_EXPR.
4473 For_statement::continue_label()
4475 if (this->continue_label_ == NULL)
4476 this->continue_label_ = new Unnamed_label(this->location());
4477 return this->continue_label_;
4480 // Set the break and continue labels a for statement. This is used
4481 // when lowering a for range statement.
4484 For_statement::set_break_continue_labels(Unnamed_label* break_label,
4485 Unnamed_label* continue_label)
4487 gcc_assert(this->break_label_ == NULL && this->continue_label_ == NULL);
4488 this->break_label_ = break_label;
4489 this->continue_label_ = continue_label;
4492 // Make a for statement.
4495 Statement::make_for_statement(Block* init, Expression* cond, Block* post,
4496 source_location location)
4498 return new For_statement(init, cond, post, location);
4501 // Class For_range_statement.
4506 For_range_statement::do_traverse(Traverse* traverse)
4508 if (this->traverse_expression(traverse, &this->index_var_) == TRAVERSE_EXIT)
4509 return TRAVERSE_EXIT;
4510 if (this->value_var_ != NULL)
4512 if (this->traverse_expression(traverse, &this->value_var_)
4514 return TRAVERSE_EXIT;
4516 if (this->traverse_expression(traverse, &this->range_) == TRAVERSE_EXIT)
4517 return TRAVERSE_EXIT;
4518 return this->statements_->traverse(traverse);
4521 // Lower a for range statement. For simplicity we lower this into a
4522 // for statement, which will then be lowered in turn to goto
4526 For_range_statement::do_lower(Gogo* gogo, Block* enclosing)
4528 Type* range_type = this->range_->type();
4529 if (range_type->points_to() != NULL
4530 && range_type->points_to()->array_type() != NULL
4531 && !range_type->points_to()->is_open_array_type())
4532 range_type = range_type->points_to();
4535 Type* value_type = NULL;
4536 if (range_type->array_type() != NULL)
4538 index_type = Type::lookup_integer_type("int");
4539 value_type = range_type->array_type()->element_type();
4541 else if (range_type->is_string_type())
4543 index_type = Type::lookup_integer_type("int");
4544 value_type = index_type;
4546 else if (range_type->map_type() != NULL)
4548 index_type = range_type->map_type()->key_type();
4549 value_type = range_type->map_type()->val_type();
4551 else if (range_type->channel_type() != NULL)
4553 index_type = range_type->channel_type()->element_type();
4554 if (this->value_var_ != NULL)
4556 if (!this->value_var_->type()->is_error_type())
4557 this->report_error(_("too many variables for range clause "
4559 return Statement::make_error_statement(this->location());
4564 this->report_error(_("range clause must have "
4565 "array, slice, setring, map, or channel type"));
4566 return Statement::make_error_statement(this->location());
4569 source_location loc = this->location();
4570 Block* temp_block = new Block(enclosing, loc);
4572 Named_object* range_object = NULL;
4573 Temporary_statement* range_temp = NULL;
4574 Var_expression* ve = this->range_->var_expression();
4576 range_object = ve->named_object();
4579 range_temp = Statement::make_temporary(NULL, this->range_, loc);
4580 temp_block->add_statement(range_temp);
4583 Temporary_statement* index_temp = Statement::make_temporary(index_type,
4585 temp_block->add_statement(index_temp);
4587 Temporary_statement* value_temp = NULL;
4588 if (this->value_var_ != NULL)
4590 value_temp = Statement::make_temporary(value_type, NULL, loc);
4591 temp_block->add_statement(value_temp);
4594 Block* body = new Block(temp_block, loc);
4601 // Arrange to do a loop appropriate for the type. We will produce
4602 // for INIT ; COND ; POST {
4604 // INDEX = INDEX_TEMP
4605 // VALUE = VALUE_TEMP // If there is a value
4606 // original statements
4609 if (range_type->array_type() != NULL)
4610 this->lower_range_array(gogo, temp_block, body, range_object, range_temp,
4611 index_temp, value_temp, &init, &cond, &iter_init,
4613 else if (range_type->is_string_type())
4614 this->lower_range_string(gogo, temp_block, body, range_object, range_temp,
4615 index_temp, value_temp, &init, &cond, &iter_init,
4617 else if (range_type->map_type() != NULL)
4618 this->lower_range_map(gogo, temp_block, body, range_object, range_temp,
4619 index_temp, value_temp, &init, &cond, &iter_init,
4621 else if (range_type->channel_type() != NULL)
4622 this->lower_range_channel(gogo, temp_block, body, range_object, range_temp,
4623 index_temp, value_temp, &init, &cond, &iter_init,
4628 if (iter_init != NULL)
4629 body->add_statement(Statement::make_block_statement(iter_init, loc));
4632 Expression* index_ref = Expression::make_temporary_reference(index_temp, loc);
4633 if (this->value_var_ == NULL)
4635 assign = Statement::make_assignment(this->index_var_, index_ref, loc);
4639 Expression_list* lhs = new Expression_list();
4640 lhs->push_back(this->index_var_);
4641 lhs->push_back(this->value_var_);
4643 Expression_list* rhs = new Expression_list();
4644 rhs->push_back(index_ref);
4645 rhs->push_back(Expression::make_temporary_reference(value_temp, loc));
4647 assign = Statement::make_tuple_assignment(lhs, rhs, loc);
4649 body->add_statement(assign);
4651 body->add_statement(Statement::make_block_statement(this->statements_, loc));
4653 body->set_end_location(this->statements_->end_location());
4655 For_statement* loop = Statement::make_for_statement(init, cond, post,
4657 loop->add_statements(body);
4658 loop->set_break_continue_labels(this->break_label_, this->continue_label_);
4660 temp_block->add_statement(loop);
4662 return Statement::make_block_statement(temp_block, loc);
4665 // Return a reference to the range, which may be in RANGE_OBJECT or in
4669 For_range_statement::make_range_ref(Named_object* range_object,
4670 Temporary_statement* range_temp,
4671 source_location loc)
4673 if (range_object != NULL)
4674 return Expression::make_var_reference(range_object, loc);
4676 return Expression::make_temporary_reference(range_temp, loc);
4679 // Return a call to the predeclared function FUNCNAME passing a
4680 // reference to the temporary variable ARG.
4683 For_range_statement::call_builtin(Gogo* gogo, const char* funcname,
4685 source_location loc)
4687 Named_object* no = gogo->lookup_global(funcname);
4688 gcc_assert(no != NULL && no->is_function_declaration());
4689 Expression* func = Expression::make_func_reference(no, NULL, loc);
4690 Expression_list* params = new Expression_list();
4691 params->push_back(arg);
4692 return Expression::make_call(func, params, false, loc);
4695 // Lower a for range over an array or slice.
4698 For_range_statement::lower_range_array(Gogo* gogo,
4701 Named_object* range_object,
4702 Temporary_statement* range_temp,
4703 Temporary_statement* index_temp,
4704 Temporary_statement* value_temp,
4710 source_location loc = this->location();
4712 // The loop we generate:
4713 // len_temp := len(range)
4714 // for index_temp = 0; index_temp < len_temp; index_temp++ {
4715 // value_temp = range[index_temp]
4716 // index = index_temp
4717 // value = value_temp
4723 // len_temp = len(range)
4726 Block* init = new Block(enclosing, loc);
4728 Expression* ref = this->make_range_ref(range_object, range_temp, loc);
4729 Expression* len_call = this->call_builtin(gogo, "len", ref, loc);
4730 Temporary_statement* len_temp = Statement::make_temporary(index_temp->type(),
4732 init->add_statement(len_temp);
4735 mpz_init_set_ui(zval, 0UL);
4736 Expression* zexpr = Expression::make_integer(&zval, NULL, loc);
4739 ref = Expression::make_temporary_reference(index_temp, loc);
4740 Statement* s = Statement::make_assignment(ref, zexpr, loc);
4741 init->add_statement(s);
4746 // index_temp < len_temp
4748 ref = Expression::make_temporary_reference(index_temp, loc);
4749 Expression* ref2 = Expression::make_temporary_reference(len_temp, loc);
4750 Expression* lt = Expression::make_binary(OPERATOR_LT, ref, ref2, loc);
4754 // Set *PITER_INIT to
4755 // value_temp = range[index_temp]
4757 Block* iter_init = NULL;
4758 if (value_temp != NULL)
4760 iter_init = new Block(body_block, loc);
4762 ref = this->make_range_ref(range_object, range_temp, loc);
4763 Expression* ref2 = Expression::make_temporary_reference(index_temp, loc);
4764 Expression* index = Expression::make_index(ref, ref2, NULL, loc);
4766 ref = Expression::make_temporary_reference(value_temp, loc);
4767 s = Statement::make_assignment(ref, index, loc);
4769 iter_init->add_statement(s);
4771 *piter_init = iter_init;
4776 Block* post = new Block(enclosing, loc);
4777 ref = Expression::make_temporary_reference(index_temp, loc);
4778 s = Statement::make_inc_statement(ref);
4779 post->add_statement(s);
4783 // Lower a for range over a string.
4786 For_range_statement::lower_range_string(Gogo* gogo,
4789 Named_object* range_object,
4790 Temporary_statement* range_temp,
4791 Temporary_statement* index_temp,
4792 Temporary_statement* value_temp,
4798 source_location loc = this->location();
4800 // The loop we generate:
4801 // var next_index_temp int
4802 // for index_temp = 0; ; index_temp = next_index_temp {
4803 // next_index_temp, value_temp = stringiter2(range, index_temp)
4804 // if next_index_temp == 0 {
4807 // index = index_temp
4808 // value = value_temp
4813 // var next_index_temp int
4816 Block* init = new Block(enclosing, loc);
4818 Temporary_statement* next_index_temp =
4819 Statement::make_temporary(index_temp->type(), NULL, loc);
4820 init->add_statement(next_index_temp);
4823 mpz_init_set_ui(zval, 0UL);
4824 Expression* zexpr = Expression::make_integer(&zval, NULL, loc);
4826 Expression* ref = Expression::make_temporary_reference(index_temp, loc);
4827 Statement* s = Statement::make_assignment(ref, zexpr, loc);
4829 init->add_statement(s);
4832 // The loop has no condition.
4836 // Set *PITER_INIT to
4837 // next_index_temp = runtime.stringiter(range, index_temp)
4839 // next_index_temp, value_temp = runtime.stringiter2(range, index_temp)
4841 // if next_index_temp == 0 {
4845 Block* iter_init = new Block(body_block, loc);
4848 if (value_temp == NULL)
4850 static Named_object* stringiter;
4851 if (stringiter == NULL)
4853 source_location bloc = BUILTINS_LOCATION;
4854 Type* int_type = gogo->lookup_global("int")->type_value();
4856 Typed_identifier_list* params = new Typed_identifier_list();
4857 params->push_back(Typed_identifier("s", Type::make_string_type(),
4859 params->push_back(Typed_identifier("k", int_type, bloc));
4861 Typed_identifier_list* results = new Typed_identifier_list();
4862 results->push_back(Typed_identifier("", int_type, bloc));
4864 Function_type* fntype = Type::make_function_type(NULL, params,
4866 stringiter = Named_object::make_function_declaration("stringiter",
4869 const char* n = "runtime.stringiter";
4870 stringiter->func_declaration_value()->set_asm_name(n);
4876 static Named_object* stringiter2;
4877 if (stringiter2 == NULL)
4879 source_location bloc = BUILTINS_LOCATION;
4880 Type* int_type = gogo->lookup_global("int")->type_value();
4882 Typed_identifier_list* params = new Typed_identifier_list();
4883 params->push_back(Typed_identifier("s", Type::make_string_type(),
4885 params->push_back(Typed_identifier("k", int_type, bloc));
4887 Typed_identifier_list* results = new Typed_identifier_list();
4888 results->push_back(Typed_identifier("", int_type, bloc));
4889 results->push_back(Typed_identifier("", int_type, bloc));
4891 Function_type* fntype = Type::make_function_type(NULL, params,
4893 stringiter2 = Named_object::make_function_declaration("stringiter",
4896 const char* n = "runtime.stringiter2";
4897 stringiter2->func_declaration_value()->set_asm_name(n);
4902 Expression* func = Expression::make_func_reference(no, NULL, loc);
4903 Expression_list* params = new Expression_list();
4904 params->push_back(this->make_range_ref(range_object, range_temp, loc));
4905 params->push_back(Expression::make_temporary_reference(index_temp, loc));
4906 Call_expression* call = Expression::make_call(func, params, false, loc);
4908 if (value_temp == NULL)
4910 ref = Expression::make_temporary_reference(next_index_temp, loc);
4911 s = Statement::make_assignment(ref, call, loc);
4915 Expression_list* lhs = new Expression_list();
4916 lhs->push_back(Expression::make_temporary_reference(next_index_temp,
4918 lhs->push_back(Expression::make_temporary_reference(value_temp, loc));
4920 Expression_list* rhs = new Expression_list();
4921 rhs->push_back(Expression::make_call_result(call, 0));
4922 rhs->push_back(Expression::make_call_result(call, 1));
4924 s = Statement::make_tuple_assignment(lhs, rhs, loc);
4926 iter_init->add_statement(s);
4928 ref = Expression::make_temporary_reference(next_index_temp, loc);
4929 zexpr = Expression::make_integer(&zval, NULL, loc);
4931 Expression* equals = Expression::make_binary(OPERATOR_EQEQ, ref, zexpr, loc);
4933 Block* then_block = new Block(iter_init, loc);
4934 s = Statement::make_break_statement(this->break_label(), loc);
4935 then_block->add_statement(s);
4937 s = Statement::make_if_statement(equals, then_block, NULL, loc);
4938 iter_init->add_statement(s);
4940 *piter_init = iter_init;
4943 // index_temp = next_index_temp
4945 Block* post = new Block(enclosing, loc);
4947 Expression* lhs = Expression::make_temporary_reference(index_temp, loc);
4948 Expression* rhs = Expression::make_temporary_reference(next_index_temp, loc);
4949 s = Statement::make_assignment(lhs, rhs, loc);
4951 post->add_statement(s);
4955 // Lower a for range over a map.
4958 For_range_statement::lower_range_map(Gogo* gogo,
4961 Named_object* range_object,
4962 Temporary_statement* range_temp,
4963 Temporary_statement* index_temp,
4964 Temporary_statement* value_temp,
4970 source_location loc = this->location();
4972 // The runtime uses a struct to handle ranges over a map. The
4973 // struct is four pointers long. The first pointer is NULL when we
4974 // have completed the iteration.
4976 // The loop we generate:
4977 // var hiter map_iteration_struct
4978 // for mapiterinit(range, &hiter); hiter[0] != nil; mapiternext(&hiter) {
4979 // mapiter2(hiter, &index_temp, &value_temp)
4980 // index = index_temp
4981 // value = value_temp
4986 // var hiter map_iteration_struct
4987 // runtime.mapiterinit(range, &hiter)
4989 Block* init = new Block(enclosing, loc);
4991 const unsigned long map_iteration_size = 4;
4994 mpz_init_set_ui(ival, map_iteration_size);
4995 Expression* iexpr = Expression::make_integer(&ival, NULL, loc);
4998 Type* byte_type = gogo->lookup_global("byte")->type_value();
4999 Type* ptr_type = Type::make_pointer_type(byte_type);
5001 Type* map_iteration_type = Type::make_array_type(ptr_type, iexpr);
5002 Type* map_iteration_ptr = Type::make_pointer_type(map_iteration_type);
5004 Temporary_statement* hiter = Statement::make_temporary(map_iteration_type,
5006 init->add_statement(hiter);
5008 source_location bloc = BUILTINS_LOCATION;
5009 Typed_identifier_list* param_types = new Typed_identifier_list();
5010 param_types->push_back(Typed_identifier("map", this->range_->type(), bloc));
5011 param_types->push_back(Typed_identifier("it", map_iteration_ptr, bloc));
5012 Function_type* fntype = Type::make_function_type(NULL, param_types, NULL,
5015 Named_object* mapiterinit =
5016 Named_object::make_function_declaration("mapiterinit", NULL, fntype, bloc);
5017 const char* n = "runtime.mapiterinit";
5018 mapiterinit->func_declaration_value()->set_asm_name(n);
5020 Expression* func = Expression::make_func_reference(mapiterinit, NULL, loc);
5021 Expression_list* params = new Expression_list();
5022 params->push_back(this->make_range_ref(range_object, range_temp, loc));
5023 Expression* ref = Expression::make_temporary_reference(hiter, loc);
5024 params->push_back(Expression::make_unary(OPERATOR_AND, ref, loc));
5025 Expression* call = Expression::make_call(func, params, false, loc);
5026 init->add_statement(Statement::make_statement(call));
5033 ref = Expression::make_temporary_reference(hiter, loc);
5036 mpz_init_set_ui(zval, 0UL);
5037 Expression* zexpr = Expression::make_integer(&zval, NULL, loc);
5040 Expression* index = Expression::make_index(ref, zexpr, NULL, loc);
5042 Expression* ne = Expression::make_binary(OPERATOR_NOTEQ, index,
5043 Expression::make_nil(loc),
5048 // Set *PITER_INIT to
5049 // mapiter1(hiter, &index_temp)
5051 // mapiter2(hiter, &index_temp, &value_temp)
5053 Block* iter_init = new Block(body_block, loc);
5055 param_types = new Typed_identifier_list();
5056 param_types->push_back(Typed_identifier("hiter", map_iteration_ptr, bloc));
5057 Type* pkey_type = Type::make_pointer_type(index_temp->type());
5058 param_types->push_back(Typed_identifier("key", pkey_type, bloc));
5059 if (value_temp != NULL)
5061 Type* pval_type = Type::make_pointer_type(value_temp->type());
5062 param_types->push_back(Typed_identifier("val", pval_type, bloc));
5064 fntype = Type::make_function_type(NULL, param_types, NULL, bloc);
5065 n = value_temp == NULL ? "mapiter1" : "mapiter2";
5066 Named_object* mapiter = Named_object::make_function_declaration(n, NULL,
5068 n = value_temp == NULL ? "runtime.mapiter1" : "runtime.mapiter2";
5069 mapiter->func_declaration_value()->set_asm_name(n);
5071 func = Expression::make_func_reference(mapiter, NULL, loc);
5072 params = new Expression_list();
5073 ref = Expression::make_temporary_reference(hiter, loc);
5074 params->push_back(Expression::make_unary(OPERATOR_AND, ref, loc));
5075 ref = Expression::make_temporary_reference(index_temp, loc);
5076 params->push_back(Expression::make_unary(OPERATOR_AND, ref, loc));
5077 if (value_temp != NULL)
5079 ref = Expression::make_temporary_reference(value_temp, loc);
5080 params->push_back(Expression::make_unary(OPERATOR_AND, ref, loc));
5082 call = Expression::make_call(func, params, false, loc);
5083 iter_init->add_statement(Statement::make_statement(call));
5085 *piter_init = iter_init;
5088 // mapiternext(&hiter)
5090 Block* post = new Block(enclosing, loc);
5092 static Named_object* mapiternext;
5093 if (mapiternext == NULL)
5095 param_types = new Typed_identifier_list();
5096 param_types->push_back(Typed_identifier("it", map_iteration_ptr, bloc));
5097 fntype = Type::make_function_type(NULL, param_types, NULL, bloc);
5098 mapiternext = Named_object::make_function_declaration("mapiternext",
5101 const char* n = "runtime.mapiternext";
5102 mapiternext->func_declaration_value()->set_asm_name(n);
5105 func = Expression::make_func_reference(mapiternext, NULL, loc);
5106 params = new Expression_list();
5107 ref = Expression::make_temporary_reference(hiter, loc);
5108 params->push_back(Expression::make_unary(OPERATOR_AND, ref, loc));
5109 call = Expression::make_call(func, params, false, loc);
5110 post->add_statement(Statement::make_statement(call));
5115 // Lower a for range over a channel.
5118 For_range_statement::lower_range_channel(Gogo* gogo,
5121 Named_object* range_object,
5122 Temporary_statement* range_temp,
5123 Temporary_statement* index_temp,
5124 Temporary_statement* value_temp,
5130 gcc_assert(value_temp == NULL);
5132 source_location loc = this->location();
5134 // The loop we generate:
5136 // index_temp = <-range
5137 // if closed(range) {
5140 // index = index_temp
5141 // value = value_temp
5145 // We have no initialization code, no condition, and no post code.
5151 // Set *PITER_INIT to
5152 // index_temp = <-range
5153 // if closed(range) {
5157 Block* iter_init = new Block(body_block, loc);
5159 Expression* ref = this->make_range_ref(range_object, range_temp, loc);
5160 Expression* cond = this->call_builtin(gogo, "closed", ref, loc);
5162 ref = this->make_range_ref(range_object, range_temp, loc);
5163 Expression* recv = Expression::make_receive(ref, loc);
5164 ref = Expression::make_temporary_reference(index_temp, loc);
5165 Statement* s = Statement::make_assignment(ref, recv, loc);
5166 iter_init->add_statement(s);
5168 Block* then_block = new Block(iter_init, loc);
5169 s = Statement::make_break_statement(this->break_label(), loc);
5170 then_block->add_statement(s);
5172 s = Statement::make_if_statement(cond, then_block, NULL, loc);
5173 iter_init->add_statement(s);
5175 *piter_init = iter_init;
5178 // Return the break LABEL_EXPR.
5181 For_range_statement::break_label()
5183 if (this->break_label_ == NULL)
5184 this->break_label_ = new Unnamed_label(this->location());
5185 return this->break_label_;
5188 // Return the continue LABEL_EXPR.
5191 For_range_statement::continue_label()
5193 if (this->continue_label_ == NULL)
5194 this->continue_label_ = new Unnamed_label(this->location());
5195 return this->continue_label_;
5198 // Make a for statement with a range clause.
5200 For_range_statement*
5201 Statement::make_for_range_statement(Expression* index_var,
5202 Expression* value_var,
5204 source_location location)
5206 return new For_range_statement(index_var, value_var, range, location);