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()
112 & (Traverse::traverse_types | Traverse::traverse_expressions)) == 0)
113 return TRAVERSE_CONTINUE;
114 return expr_list->traverse(traverse);
117 // Traverse a type in a statement. This is a helper function for
121 Statement::traverse_type(Traverse* traverse, Type* type)
123 if ((traverse->traverse_mask()
124 & (Traverse::traverse_types | Traverse::traverse_expressions)) == 0)
125 return TRAVERSE_CONTINUE;
126 return Type::traverse(type, traverse);
129 // Set type information for unnamed constants. This is really done by
133 Statement::determine_types()
135 this->do_determine_types();
138 // If this is a thunk statement, return it.
141 Statement::thunk_statement()
143 Thunk_statement* ret = this->convert<Thunk_statement, STATEMENT_GO>();
145 ret = this->convert<Thunk_statement, STATEMENT_DEFER>();
149 // Get a tree for a Statement. This is really done by the child
153 Statement::get_tree(Translate_context* context)
155 if (this->classification_ == STATEMENT_ERROR)
156 return error_mark_node;
158 return this->do_get_tree(context);
161 // Build tree nodes and set locations.
164 Statement::build_stmt_1(int tree_code_value, tree node)
166 tree ret = build1(static_cast<tree_code>(tree_code_value),
167 void_type_node, node);
168 SET_EXPR_LOCATION(ret, this->location_);
172 // Note that this statement is erroneous. This is called by children
173 // when they discover an error.
176 Statement::set_is_error()
178 this->classification_ = STATEMENT_ERROR;
181 // For children to call to report an error conveniently.
184 Statement::report_error(const char* msg)
186 error_at(this->location_, "%s", msg);
187 this->set_is_error();
190 // An error statement, used to avoid crashing after we report an
193 class Error_statement : public Statement
196 Error_statement(source_location location)
197 : Statement(STATEMENT_ERROR, location)
202 do_traverse(Traverse*)
203 { return TRAVERSE_CONTINUE; }
206 do_get_tree(Translate_context*)
207 { gcc_unreachable(); }
210 // Make an error statement.
213 Statement::make_error_statement(source_location location)
215 return new Error_statement(location);
218 // Class Variable_declaration_statement.
220 Variable_declaration_statement::Variable_declaration_statement(
222 : Statement(STATEMENT_VARIABLE_DECLARATION, var->var_value()->location()),
227 // We don't actually traverse the variable here; it was traversed
228 // while traversing the Block.
231 Variable_declaration_statement::do_traverse(Traverse*)
233 return TRAVERSE_CONTINUE;
236 // Traverse the assignments in a variable declaration. Note that this
237 // traversal is different from the usual traversal.
240 Variable_declaration_statement::do_traverse_assignments(
241 Traverse_assignments* tassign)
243 tassign->initialize_variable(this->var_);
247 // Return the tree for a variable declaration.
250 Variable_declaration_statement::do_get_tree(Translate_context* context)
252 tree val = this->var_->get_tree(context->gogo(), context->function());
253 if (val == error_mark_node || TREE_TYPE(val) == error_mark_node)
254 return error_mark_node;
255 Variable* variable = this->var_->var_value();
257 tree init = variable->get_init_tree(context->gogo(), context->function());
258 if (init == error_mark_node)
259 return error_mark_node;
261 // If this variable lives on the heap, we need to allocate it now.
262 if (!variable->is_in_heap())
264 DECL_INITIAL(val) = init;
265 return this->build_stmt_1(DECL_EXPR, val);
269 gcc_assert(TREE_CODE(val) == INDIRECT_REF);
270 tree decl = TREE_OPERAND(val, 0);
271 gcc_assert(TREE_CODE(decl) == VAR_DECL);
272 tree type = TREE_TYPE(decl);
273 gcc_assert(POINTER_TYPE_P(type));
274 tree size = TYPE_SIZE_UNIT(TREE_TYPE(type));
275 tree space = context->gogo()->allocate_memory(variable->type(), size,
277 space = fold_convert(TREE_TYPE(decl), space);
278 DECL_INITIAL(decl) = space;
279 return build2(COMPOUND_EXPR, void_type_node,
280 this->build_stmt_1(DECL_EXPR, decl),
281 build2(MODIFY_EXPR, void_type_node, val, init));
285 // Make a variable declaration.
288 Statement::make_variable_declaration(Named_object* var)
290 return new Variable_declaration_statement(var);
293 // Class Temporary_statement.
295 // Return the type of the temporary variable.
298 Temporary_statement::type() const
300 return this->type_ != NULL ? this->type_ : this->init_->type();
303 // Return the tree for the temporary variable.
306 Temporary_statement::get_decl() const
308 if (this->decl_ == NULL)
310 gcc_assert(saw_errors());
311 return error_mark_node;
319 Temporary_statement::do_traverse(Traverse* traverse)
321 if (this->type_ != NULL
322 && this->traverse_type(traverse, this->type_) == TRAVERSE_EXIT)
323 return TRAVERSE_EXIT;
324 if (this->init_ == NULL)
325 return TRAVERSE_CONTINUE;
327 return this->traverse_expression(traverse, &this->init_);
330 // Traverse assignments.
333 Temporary_statement::do_traverse_assignments(Traverse_assignments* tassign)
335 if (this->init_ == NULL)
337 tassign->value(&this->init_, true, true);
344 Temporary_statement::do_determine_types()
346 if (this->type_ != NULL && this->type_->is_abstract())
347 this->type_ = this->type_->make_non_abstract_type();
349 if (this->init_ != NULL)
351 if (this->type_ == NULL)
352 this->init_->determine_type_no_context();
355 Type_context context(this->type_, false);
356 this->init_->determine_type(&context);
360 if (this->type_ == NULL)
362 this->type_ = this->init_->type();
363 gcc_assert(!this->type_->is_abstract());
370 Temporary_statement::do_check_types(Gogo*)
372 if (this->type_ != NULL && this->init_ != NULL)
375 if (!Type::are_assignable(this->type_, this->init_->type(), &reason))
378 error_at(this->location(), "incompatible types in assignment");
380 error_at(this->location(), "incompatible types in assignment (%s)",
382 this->set_is_error();
390 Temporary_statement::do_get_tree(Translate_context* context)
392 gcc_assert(this->decl_ == NULL_TREE);
393 tree type_tree = this->type()->get_tree(context->gogo());
394 tree init_tree = (this->init_ == NULL
396 : this->init_->get_tree(context));
397 if (type_tree == error_mark_node || init_tree == error_mark_node)
399 this->decl_ = error_mark_node;
400 return error_mark_node;
402 // We can only use create_tmp_var if the type is not addressable.
403 if (!TREE_ADDRESSABLE(type_tree))
405 this->decl_ = create_tmp_var(type_tree, "GOTMP");
406 DECL_SOURCE_LOCATION(this->decl_) = this->location();
410 gcc_assert(context->function() != NULL && context->block() != NULL);
411 tree decl = build_decl(this->location(), VAR_DECL,
412 create_tmp_var_name("GOTMP"),
414 DECL_ARTIFICIAL(decl) = 1;
415 DECL_IGNORED_P(decl) = 1;
417 gcc_assert(current_function_decl != NULL_TREE);
418 DECL_CONTEXT(decl) = current_function_decl;
420 // We have to add this variable to the block so that it winds up
422 tree block_tree = context->block_tree();
423 gcc_assert(block_tree != NULL_TREE);
424 DECL_CHAIN(decl) = BLOCK_VARS(block_tree);
425 BLOCK_VARS(block_tree) = decl;
429 if (init_tree != NULL_TREE)
430 DECL_INITIAL(this->decl_) =
431 Expression::convert_for_assignment(context, this->type(),
432 this->init_->type(), init_tree,
434 if (this->is_address_taken_)
435 TREE_ADDRESSABLE(this->decl_) = 1;
436 return this->build_stmt_1(DECL_EXPR, this->decl_);
439 // Make and initialize a temporary variable in BLOCK.
442 Statement::make_temporary(Type* type, Expression* init,
443 source_location location)
445 return new Temporary_statement(type, init, location);
448 // An assignment statement.
450 class Assignment_statement : public Statement
453 Assignment_statement(Expression* lhs, Expression* rhs,
454 source_location location)
455 : Statement(STATEMENT_ASSIGNMENT, location),
461 do_traverse(Traverse* traverse);
464 do_traverse_assignments(Traverse_assignments*);
467 do_determine_types();
470 do_check_types(Gogo*);
473 do_get_tree(Translate_context*);
476 // Left hand side--the lvalue.
478 // Right hand side--the rvalue.
485 Assignment_statement::do_traverse(Traverse* traverse)
487 if (this->traverse_expression(traverse, &this->lhs_) == TRAVERSE_EXIT)
488 return TRAVERSE_EXIT;
489 return this->traverse_expression(traverse, &this->rhs_);
493 Assignment_statement::do_traverse_assignments(Traverse_assignments* tassign)
495 tassign->assignment(&this->lhs_, &this->rhs_);
499 // Set types for the assignment.
502 Assignment_statement::do_determine_types()
504 this->lhs_->determine_type_no_context();
505 Type_context context(this->lhs_->type(), false);
506 this->rhs_->determine_type(&context);
509 // Check types for an assignment.
512 Assignment_statement::do_check_types(Gogo*)
514 // The left hand side must be either addressable, a map index
515 // expression, or the blank identifier.
516 if (!this->lhs_->is_addressable()
517 && this->lhs_->map_index_expression() == NULL
518 && !this->lhs_->is_sink_expression())
520 if (!this->lhs_->type()->is_error_type())
521 this->report_error(_("invalid left hand side of assignment"));
525 Type* lhs_type = this->lhs_->type();
526 Type* rhs_type = this->rhs_->type();
528 if (!Type::are_assignable(lhs_type, rhs_type, &reason))
531 error_at(this->location(), "incompatible types in assignment");
533 error_at(this->location(), "incompatible types in assignment (%s)",
535 this->set_is_error();
538 if (lhs_type->is_error_type()
539 || rhs_type->is_error_type()
540 || lhs_type->is_undefined()
541 || rhs_type->is_undefined())
543 // Make sure we get the error for an undefined type.
546 this->set_is_error();
550 // Build a tree for an assignment statement.
553 Assignment_statement::do_get_tree(Translate_context* context)
555 tree rhs_tree = this->rhs_->get_tree(context);
557 if (this->lhs_->is_sink_expression())
560 tree lhs_tree = this->lhs_->get_tree(context);
562 if (lhs_tree == error_mark_node || rhs_tree == error_mark_node)
563 return error_mark_node;
565 rhs_tree = Expression::convert_for_assignment(context, this->lhs_->type(),
566 this->rhs_->type(), rhs_tree,
568 if (rhs_tree == error_mark_node)
569 return error_mark_node;
571 return fold_build2_loc(this->location(), MODIFY_EXPR, void_type_node,
575 // Make an assignment statement.
578 Statement::make_assignment(Expression* lhs, Expression* rhs,
579 source_location location)
581 return new Assignment_statement(lhs, rhs, location);
584 // The Move_ordered_evals class is used to find any subexpressions of
585 // an expression that have an evaluation order dependency. It creates
586 // temporary variables to hold them.
588 class Move_ordered_evals : public Traverse
591 Move_ordered_evals(Block* block)
592 : Traverse(traverse_expressions),
598 expression(Expression**);
601 // The block where new temporary variables should be added.
606 Move_ordered_evals::expression(Expression** pexpr)
608 // We have to look at subexpressions first.
609 if ((*pexpr)->traverse_subexpressions(this) == TRAVERSE_EXIT)
610 return TRAVERSE_EXIT;
611 if ((*pexpr)->must_eval_in_order())
613 source_location loc = (*pexpr)->location();
614 Temporary_statement* temp = Statement::make_temporary(NULL, *pexpr, loc);
615 this->block_->add_statement(temp);
616 *pexpr = Expression::make_temporary_reference(temp, loc);
618 return TRAVERSE_SKIP_COMPONENTS;
621 // An assignment operation statement.
623 class Assignment_operation_statement : public Statement
626 Assignment_operation_statement(Operator op, Expression* lhs, Expression* rhs,
627 source_location location)
628 : Statement(STATEMENT_ASSIGNMENT_OPERATION, location),
629 op_(op), lhs_(lhs), rhs_(rhs)
634 do_traverse(Traverse*);
637 do_traverse_assignments(Traverse_assignments*)
638 { gcc_unreachable(); }
641 do_lower(Gogo*, Block*);
644 do_get_tree(Translate_context*)
645 { gcc_unreachable(); }
648 // The operator (OPERATOR_PLUSEQ, etc.).
659 Assignment_operation_statement::do_traverse(Traverse* traverse)
661 if (this->traverse_expression(traverse, &this->lhs_) == TRAVERSE_EXIT)
662 return TRAVERSE_EXIT;
663 return this->traverse_expression(traverse, &this->rhs_);
666 // Lower an assignment operation statement to a regular assignment
670 Assignment_operation_statement::do_lower(Gogo*, Block* enclosing)
672 source_location loc = this->location();
674 // We have to evaluate the left hand side expression only once. We
675 // do this by moving out any expression with side effects.
676 Block* b = new Block(enclosing, loc);
677 Move_ordered_evals moe(b);
678 this->lhs_->traverse_subexpressions(&moe);
680 Expression* lval = this->lhs_->copy();
685 case OPERATOR_PLUSEQ:
688 case OPERATOR_MINUSEQ:
697 case OPERATOR_MULTEQ:
706 case OPERATOR_LSHIFTEQ:
707 op = OPERATOR_LSHIFT;
709 case OPERATOR_RSHIFTEQ:
710 op = OPERATOR_RSHIFT;
715 case OPERATOR_BITCLEAREQ:
716 op = OPERATOR_BITCLEAR;
722 Expression* binop = Expression::make_binary(op, lval, this->rhs_, loc);
723 Statement* s = Statement::make_assignment(this->lhs_, binop, loc);
724 if (b->statements()->empty())
732 return Statement::make_block_statement(b, loc);
736 // Make an assignment operation statement.
739 Statement::make_assignment_operation(Operator op, Expression* lhs,
740 Expression* rhs, source_location location)
742 return new Assignment_operation_statement(op, lhs, rhs, location);
745 // A tuple assignment statement. This differs from an assignment
746 // statement in that the right-hand-side expressions are evaluated in
749 class Tuple_assignment_statement : public Statement
752 Tuple_assignment_statement(Expression_list* lhs, Expression_list* rhs,
753 source_location location)
754 : Statement(STATEMENT_TUPLE_ASSIGNMENT, location),
760 do_traverse(Traverse* traverse);
763 do_traverse_assignments(Traverse_assignments*)
764 { gcc_unreachable(); }
767 do_lower(Gogo*, Block*);
770 do_get_tree(Translate_context*)
771 { gcc_unreachable(); }
774 // Left hand side--a list of lvalues.
775 Expression_list* lhs_;
776 // Right hand side--a list of rvalues.
777 Expression_list* rhs_;
783 Tuple_assignment_statement::do_traverse(Traverse* traverse)
785 if (this->traverse_expression_list(traverse, this->lhs_) == TRAVERSE_EXIT)
786 return TRAVERSE_EXIT;
787 return this->traverse_expression_list(traverse, this->rhs_);
790 // Lower a tuple assignment. We use temporary variables to split it
791 // up into a set of single assignments.
794 Tuple_assignment_statement::do_lower(Gogo*, Block* enclosing)
796 source_location loc = this->location();
798 Block* b = new Block(enclosing, loc);
800 // First move out any subexpressions on the left hand side. The
801 // right hand side will be evaluated in the required order anyhow.
802 Move_ordered_evals moe(b);
803 for (Expression_list::const_iterator plhs = this->lhs_->begin();
804 plhs != this->lhs_->end();
806 (*plhs)->traverse_subexpressions(&moe);
808 std::vector<Temporary_statement*> temps;
809 temps.reserve(this->lhs_->size());
811 Expression_list::const_iterator prhs = this->rhs_->begin();
812 for (Expression_list::const_iterator plhs = this->lhs_->begin();
813 plhs != this->lhs_->end();
816 gcc_assert(prhs != this->rhs_->end());
818 if ((*plhs)->is_error_expression()
819 || (*plhs)->type()->is_error_type()
820 || (*prhs)->is_error_expression()
821 || (*prhs)->type()->is_error_type())
824 if ((*plhs)->is_sink_expression())
826 b->add_statement(Statement::make_statement(*prhs));
830 Temporary_statement* temp = Statement::make_temporary((*plhs)->type(),
832 b->add_statement(temp);
833 temps.push_back(temp);
836 gcc_assert(prhs == this->rhs_->end());
838 prhs = this->rhs_->begin();
839 std::vector<Temporary_statement*>::const_iterator ptemp = temps.begin();
840 for (Expression_list::const_iterator plhs = this->lhs_->begin();
841 plhs != this->lhs_->end();
844 if ((*plhs)->is_error_expression()
845 || (*plhs)->type()->is_error_type()
846 || (*prhs)->is_error_expression()
847 || (*prhs)->type()->is_error_type())
850 if ((*plhs)->is_sink_expression())
853 Expression* ref = Expression::make_temporary_reference(*ptemp, loc);
854 Statement* s = Statement::make_assignment(*plhs, ref, loc);
858 gcc_assert(ptemp == temps.end());
860 return Statement::make_block_statement(b, loc);
863 // Make a tuple assignment statement.
866 Statement::make_tuple_assignment(Expression_list* lhs, Expression_list* rhs,
867 source_location location)
869 return new Tuple_assignment_statement(lhs, rhs, location);
872 // A tuple assignment from a map index expression.
875 class Tuple_map_assignment_statement : public Statement
878 Tuple_map_assignment_statement(Expression* val, Expression* present,
879 Expression* map_index,
880 source_location location)
881 : Statement(STATEMENT_TUPLE_MAP_ASSIGNMENT, location),
882 val_(val), present_(present), map_index_(map_index)
887 do_traverse(Traverse* traverse);
890 do_traverse_assignments(Traverse_assignments*)
891 { gcc_unreachable(); }
894 do_lower(Gogo*, Block*);
897 do_get_tree(Translate_context*)
898 { gcc_unreachable(); }
901 // Lvalue which receives the value from the map.
903 // Lvalue which receives whether the key value was present.
904 Expression* present_;
905 // The map index expression.
906 Expression* map_index_;
912 Tuple_map_assignment_statement::do_traverse(Traverse* traverse)
914 if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT
915 || this->traverse_expression(traverse, &this->present_) == TRAVERSE_EXIT)
916 return TRAVERSE_EXIT;
917 return this->traverse_expression(traverse, &this->map_index_);
920 // Lower a tuple map assignment.
923 Tuple_map_assignment_statement::do_lower(Gogo*, Block* enclosing)
925 source_location loc = this->location();
927 Map_index_expression* map_index = this->map_index_->map_index_expression();
928 if (map_index == NULL)
930 this->report_error(_("expected map index on right hand side"));
931 return Statement::make_error_statement(loc);
933 Map_type* map_type = map_index->get_map_type();
934 if (map_type == NULL)
935 return Statement::make_error_statement(loc);
937 Block* b = new Block(enclosing, loc);
939 // Move out any subexpressions to make sure that functions are
940 // called in the required order.
941 Move_ordered_evals moe(b);
942 this->val_->traverse_subexpressions(&moe);
943 this->present_->traverse_subexpressions(&moe);
945 // Copy the key value into a temporary so that we can take its
946 // address without pushing the value onto the heap.
948 // var key_temp KEY_TYPE = MAP_INDEX
949 Temporary_statement* key_temp =
950 Statement::make_temporary(map_type->key_type(), map_index->index(), loc);
951 b->add_statement(key_temp);
953 // var val_temp VAL_TYPE
954 Temporary_statement* val_temp =
955 Statement::make_temporary(map_type->val_type(), NULL, loc);
956 b->add_statement(val_temp);
958 // var present_temp bool
959 Temporary_statement* present_temp =
960 Statement::make_temporary(Type::lookup_bool_type(), NULL, loc);
961 b->add_statement(present_temp);
963 // func mapaccess2(hmap map[k]v, key *k, val *v) bool
964 source_location bloc = BUILTINS_LOCATION;
965 Typed_identifier_list* param_types = new Typed_identifier_list();
966 param_types->push_back(Typed_identifier("hmap", map_type, bloc));
967 Type* pkey_type = Type::make_pointer_type(map_type->key_type());
968 param_types->push_back(Typed_identifier("key", pkey_type, bloc));
969 Type* pval_type = Type::make_pointer_type(map_type->val_type());
970 param_types->push_back(Typed_identifier("val", pval_type, bloc));
972 Typed_identifier_list* ret_types = new Typed_identifier_list();
973 ret_types->push_back(Typed_identifier("", Type::lookup_bool_type(), bloc));
975 Function_type* fntype = Type::make_function_type(NULL, param_types,
977 Named_object* mapaccess2 =
978 Named_object::make_function_declaration("mapaccess2", NULL, fntype, bloc);
979 mapaccess2->func_declaration_value()->set_asm_name("runtime.mapaccess2");
981 // present_temp = mapaccess2(MAP, &key_temp, &val_temp)
982 Expression* func = Expression::make_func_reference(mapaccess2, NULL, loc);
983 Expression_list* params = new Expression_list();
984 params->push_back(map_index->map());
985 Expression* ref = Expression::make_temporary_reference(key_temp, loc);
986 params->push_back(Expression::make_unary(OPERATOR_AND, ref, loc));
987 ref = Expression::make_temporary_reference(val_temp, loc);
988 params->push_back(Expression::make_unary(OPERATOR_AND, ref, loc));
989 Expression* call = Expression::make_call(func, params, false, loc);
991 ref = Expression::make_temporary_reference(present_temp, loc);
992 Statement* s = Statement::make_assignment(ref, call, loc);
996 ref = Expression::make_temporary_reference(val_temp, loc);
997 s = Statement::make_assignment(this->val_, ref, loc);
1000 // present = present_temp
1001 ref = Expression::make_temporary_reference(present_temp, loc);
1002 s = Statement::make_assignment(this->present_, ref, loc);
1003 b->add_statement(s);
1005 return Statement::make_block_statement(b, loc);
1008 // Make a map assignment statement which returns a pair of values.
1011 Statement::make_tuple_map_assignment(Expression* val, Expression* present,
1012 Expression* map_index,
1013 source_location location)
1015 return new Tuple_map_assignment_statement(val, present, map_index, location);
1018 // Assign a pair of entries to a map.
1021 class Map_assignment_statement : public Statement
1024 Map_assignment_statement(Expression* map_index,
1025 Expression* val, Expression* should_set,
1026 source_location location)
1027 : Statement(STATEMENT_MAP_ASSIGNMENT, location),
1028 map_index_(map_index), val_(val), should_set_(should_set)
1033 do_traverse(Traverse* traverse);
1036 do_traverse_assignments(Traverse_assignments*)
1037 { gcc_unreachable(); }
1040 do_lower(Gogo*, Block*);
1043 do_get_tree(Translate_context*)
1044 { gcc_unreachable(); }
1047 // A reference to the map index which should be set or deleted.
1048 Expression* map_index_;
1049 // The value to add to the map.
1051 // Whether or not to add the value.
1052 Expression* should_set_;
1055 // Traverse a map assignment.
1058 Map_assignment_statement::do_traverse(Traverse* traverse)
1060 if (this->traverse_expression(traverse, &this->map_index_) == TRAVERSE_EXIT
1061 || this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT)
1062 return TRAVERSE_EXIT;
1063 return this->traverse_expression(traverse, &this->should_set_);
1066 // Lower a map assignment to a function call.
1069 Map_assignment_statement::do_lower(Gogo*, Block* enclosing)
1071 source_location loc = this->location();
1073 Map_index_expression* map_index = this->map_index_->map_index_expression();
1074 if (map_index == NULL)
1076 this->report_error(_("expected map index on left hand side"));
1077 return Statement::make_error_statement(loc);
1079 Map_type* map_type = map_index->get_map_type();
1080 if (map_type == NULL)
1081 return Statement::make_error_statement(loc);
1083 Block* b = new Block(enclosing, loc);
1085 // Evaluate the map first to get order of evaluation right.
1086 // map_temp := m // we are evaluating m[k] = v, p
1087 Temporary_statement* map_temp = Statement::make_temporary(map_type,
1090 b->add_statement(map_temp);
1092 // var key_temp MAP_KEY_TYPE = k
1093 Temporary_statement* key_temp =
1094 Statement::make_temporary(map_type->key_type(), map_index->index(), loc);
1095 b->add_statement(key_temp);
1097 // var val_temp MAP_VAL_TYPE = v
1098 Temporary_statement* val_temp =
1099 Statement::make_temporary(map_type->val_type(), this->val_, loc);
1100 b->add_statement(val_temp);
1102 // func mapassign2(hmap map[k]v, key *k, val *v, p)
1103 source_location bloc = BUILTINS_LOCATION;
1104 Typed_identifier_list* param_types = new Typed_identifier_list();
1105 param_types->push_back(Typed_identifier("hmap", map_type, bloc));
1106 Type* pkey_type = Type::make_pointer_type(map_type->key_type());
1107 param_types->push_back(Typed_identifier("key", pkey_type, bloc));
1108 Type* pval_type = Type::make_pointer_type(map_type->val_type());
1109 param_types->push_back(Typed_identifier("val", pval_type, bloc));
1110 param_types->push_back(Typed_identifier("p", Type::lookup_bool_type(), bloc));
1111 Function_type* fntype = Type::make_function_type(NULL, param_types,
1113 Named_object* mapassign2 =
1114 Named_object::make_function_declaration("mapassign2", NULL, fntype, bloc);
1115 mapassign2->func_declaration_value()->set_asm_name("runtime.mapassign2");
1117 // mapassign2(map_temp, &key_temp, &val_temp, p)
1118 Expression* func = Expression::make_func_reference(mapassign2, NULL, loc);
1119 Expression_list* params = new Expression_list();
1120 params->push_back(Expression::make_temporary_reference(map_temp, loc));
1121 Expression* ref = Expression::make_temporary_reference(key_temp, loc);
1122 params->push_back(Expression::make_unary(OPERATOR_AND, ref, loc));
1123 ref = Expression::make_temporary_reference(val_temp, loc);
1124 params->push_back(Expression::make_unary(OPERATOR_AND, ref, loc));
1125 params->push_back(this->should_set_);
1126 Expression* call = Expression::make_call(func, params, false, loc);
1127 Statement* s = Statement::make_statement(call);
1128 b->add_statement(s);
1130 return Statement::make_block_statement(b, loc);
1133 // Make a statement which assigns a pair of entries to a map.
1136 Statement::make_map_assignment(Expression* map_index,
1137 Expression* val, Expression* should_set,
1138 source_location location)
1140 return new Map_assignment_statement(map_index, val, should_set, location);
1143 // A tuple assignment from a receive statement.
1145 class Tuple_receive_assignment_statement : public Statement
1148 Tuple_receive_assignment_statement(Expression* val, Expression* success,
1149 Expression* channel,
1150 source_location location)
1151 : Statement(STATEMENT_TUPLE_RECEIVE_ASSIGNMENT, location),
1152 val_(val), success_(success), channel_(channel)
1157 do_traverse(Traverse* traverse);
1160 do_traverse_assignments(Traverse_assignments*)
1161 { gcc_unreachable(); }
1164 do_lower(Gogo*, Block*);
1167 do_get_tree(Translate_context*)
1168 { gcc_unreachable(); }
1171 // Lvalue which receives the value from the channel.
1173 // Lvalue which receives whether the read succeeded or failed.
1174 Expression* success_;
1175 // The channel on which we receive the value.
1176 Expression* channel_;
1182 Tuple_receive_assignment_statement::do_traverse(Traverse* traverse)
1184 if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT
1185 || this->traverse_expression(traverse, &this->success_) == TRAVERSE_EXIT)
1186 return TRAVERSE_EXIT;
1187 return this->traverse_expression(traverse, &this->channel_);
1190 // Lower to a function call.
1193 Tuple_receive_assignment_statement::do_lower(Gogo*, Block* enclosing)
1195 source_location loc = this->location();
1197 Channel_type* channel_type = this->channel_->type()->channel_type();
1198 if (channel_type == NULL)
1200 this->report_error(_("expected channel"));
1201 return Statement::make_error_statement(loc);
1203 if (!channel_type->may_receive())
1205 this->report_error(_("invalid receive on send-only channel"));
1206 return Statement::make_error_statement(loc);
1209 Block* b = new Block(enclosing, loc);
1211 // Make sure that any subexpressions on the left hand side are
1212 // evaluated in the right order.
1213 Move_ordered_evals moe(b);
1214 this->val_->traverse_subexpressions(&moe);
1215 this->success_->traverse_subexpressions(&moe);
1217 // var val_temp ELEMENT_TYPE
1218 Temporary_statement* val_temp =
1219 Statement::make_temporary(channel_type->element_type(), NULL, loc);
1220 b->add_statement(val_temp);
1222 // var success_temp bool
1223 Temporary_statement* success_temp =
1224 Statement::make_temporary(Type::lookup_bool_type(), NULL, loc);
1225 b->add_statement(success_temp);
1227 // func chanrecv2(c chan T, val *T) bool
1228 source_location bloc = BUILTINS_LOCATION;
1229 Typed_identifier_list* param_types = new Typed_identifier_list();
1230 param_types->push_back(Typed_identifier("c", channel_type, bloc));
1231 Type* pelement_type = Type::make_pointer_type(channel_type->element_type());
1232 param_types->push_back(Typed_identifier("val", pelement_type, bloc));
1234 Typed_identifier_list* ret_types = new Typed_identifier_list();
1235 ret_types->push_back(Typed_identifier("", Type::lookup_bool_type(), bloc));
1237 Function_type* fntype = Type::make_function_type(NULL, param_types,
1239 Named_object* chanrecv2 =
1240 Named_object::make_function_declaration("chanrecv2", NULL, fntype, bloc);
1241 chanrecv2->func_declaration_value()->set_asm_name("runtime.chanrecv2");
1243 // success_temp = chanrecv2(channel, &val_temp)
1244 Expression* func = Expression::make_func_reference(chanrecv2, NULL, loc);
1245 Expression_list* params = new Expression_list();
1246 params->push_back(this->channel_);
1247 Expression* ref = Expression::make_temporary_reference(val_temp, loc);
1248 params->push_back(Expression::make_unary(OPERATOR_AND, ref, loc));
1249 Expression* call = Expression::make_call(func, params, false, loc);
1250 ref = Expression::make_temporary_reference(success_temp, loc);
1251 Statement* s = Statement::make_assignment(ref, call, loc);
1252 b->add_statement(s);
1255 ref = Expression::make_temporary_reference(val_temp, loc);
1256 s = Statement::make_assignment(this->val_, ref, loc);
1257 b->add_statement(s);
1259 // success = success_temp
1260 ref = Expression::make_temporary_reference(success_temp, loc);
1261 s = Statement::make_assignment(this->success_, ref, loc);
1262 b->add_statement(s);
1264 return Statement::make_block_statement(b, loc);
1267 // Make a nonblocking receive statement.
1270 Statement::make_tuple_receive_assignment(Expression* val, Expression* success,
1271 Expression* channel,
1272 source_location location)
1274 return new Tuple_receive_assignment_statement(val, success, channel,
1278 // An assignment to a pair of values from a type guard. This is a
1279 // conditional type guard. v, ok = i.(type).
1281 class Tuple_type_guard_assignment_statement : public Statement
1284 Tuple_type_guard_assignment_statement(Expression* val, Expression* ok,
1285 Expression* expr, Type* type,
1286 source_location location)
1287 : Statement(STATEMENT_TUPLE_TYPE_GUARD_ASSIGNMENT, location),
1288 val_(val), ok_(ok), expr_(expr), type_(type)
1293 do_traverse(Traverse*);
1296 do_traverse_assignments(Traverse_assignments*)
1297 { gcc_unreachable(); }
1300 do_lower(Gogo*, Block*);
1303 do_get_tree(Translate_context*)
1304 { gcc_unreachable(); }
1308 lower_to_empty_interface(const char*);
1311 lower_to_type(const char*);
1314 lower_to_object_type(Block*, const char*);
1316 // The variable which recieves the converted value.
1318 // The variable which receives the indication of success.
1320 // The expression being converted.
1322 // The type to which the expression is being converted.
1326 // Traverse a type guard tuple assignment.
1329 Tuple_type_guard_assignment_statement::do_traverse(Traverse* traverse)
1331 if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT
1332 || this->traverse_expression(traverse, &this->ok_) == TRAVERSE_EXIT
1333 || this->traverse_type(traverse, this->type_) == TRAVERSE_EXIT)
1334 return TRAVERSE_EXIT;
1335 return this->traverse_expression(traverse, &this->expr_);
1338 // Lower to a function call.
1341 Tuple_type_guard_assignment_statement::do_lower(Gogo*, Block* enclosing)
1343 source_location loc = this->location();
1345 Type* expr_type = this->expr_->type();
1346 if (expr_type->interface_type() == NULL)
1348 if (!expr_type->is_error_type() && !this->type_->is_error_type())
1349 this->report_error(_("type assertion only valid for interface types"));
1350 return Statement::make_error_statement(loc);
1353 Block* b = new Block(enclosing, loc);
1355 // Make sure that any subexpressions on the left hand side are
1356 // evaluated in the right order.
1357 Move_ordered_evals moe(b);
1358 this->val_->traverse_subexpressions(&moe);
1359 this->ok_->traverse_subexpressions(&moe);
1361 bool expr_is_empty = expr_type->interface_type()->is_empty();
1362 Call_expression* call;
1363 if (this->type_->interface_type() != NULL)
1365 if (this->type_->interface_type()->is_empty())
1366 call = this->lower_to_empty_interface(expr_is_empty
1370 call = this->lower_to_type(expr_is_empty ? "ifaceE2I2" : "ifaceI2I2");
1372 else if (this->type_->points_to() != NULL)
1373 call = this->lower_to_type(expr_is_empty ? "ifaceE2T2P" : "ifaceI2T2P");
1376 this->lower_to_object_type(b, expr_is_empty ? "ifaceE2T2" : "ifaceI2T2");
1382 Expression* res = Expression::make_call_result(call, 0);
1383 Statement* s = Statement::make_assignment(this->val_, res, loc);
1384 b->add_statement(s);
1386 res = Expression::make_call_result(call, 1);
1387 s = Statement::make_assignment(this->ok_, res, loc);
1388 b->add_statement(s);
1391 return Statement::make_block_statement(b, loc);
1394 // Lower a conversion to an empty interface type.
1397 Tuple_type_guard_assignment_statement::lower_to_empty_interface(
1400 source_location loc = this->location();
1402 // func FNNAME(interface) (empty, bool)
1403 source_location bloc = BUILTINS_LOCATION;
1404 Typed_identifier_list* param_types = new Typed_identifier_list();
1405 param_types->push_back(Typed_identifier("i", this->expr_->type(), bloc));
1406 Typed_identifier_list* ret_types = new Typed_identifier_list();
1407 ret_types->push_back(Typed_identifier("ret", this->type_, bloc));
1408 ret_types->push_back(Typed_identifier("ok", Type::lookup_bool_type(), bloc));
1409 Function_type* fntype = Type::make_function_type(NULL, param_types,
1412 Named_object::make_function_declaration(fnname, NULL, fntype, bloc);
1413 std::string asm_name = "runtime.";
1415 fn->func_declaration_value()->set_asm_name(asm_name);
1417 // val, ok = FNNAME(expr)
1418 Expression* func = Expression::make_func_reference(fn, NULL, loc);
1419 Expression_list* params = new Expression_list();
1420 params->push_back(this->expr_);
1421 return Expression::make_call(func, params, false, loc);
1424 // Lower a conversion to a non-empty interface type or a pointer type.
1427 Tuple_type_guard_assignment_statement::lower_to_type(const char* fnname)
1429 source_location loc = this->location();
1431 // func FNNAME(*descriptor, interface) (interface, bool)
1432 source_location bloc = BUILTINS_LOCATION;
1433 Typed_identifier_list* param_types = new Typed_identifier_list();
1434 param_types->push_back(Typed_identifier("inter",
1435 Type::make_type_descriptor_ptr_type(),
1437 param_types->push_back(Typed_identifier("i", this->expr_->type(), bloc));
1438 Typed_identifier_list* ret_types = new Typed_identifier_list();
1439 ret_types->push_back(Typed_identifier("ret", this->type_, bloc));
1440 ret_types->push_back(Typed_identifier("ok", Type::lookup_bool_type(), bloc));
1441 Function_type* fntype = Type::make_function_type(NULL, param_types,
1444 Named_object::make_function_declaration(fnname, NULL, fntype, bloc);
1445 std::string asm_name = "runtime.";
1447 fn->func_declaration_value()->set_asm_name(asm_name);
1449 // val, ok = FNNAME(type_descriptor, expr)
1450 Expression* func = Expression::make_func_reference(fn, NULL, loc);
1451 Expression_list* params = new Expression_list();
1452 params->push_back(Expression::make_type_descriptor(this->type_, loc));
1453 params->push_back(this->expr_);
1454 return Expression::make_call(func, params, false, loc);
1457 // Lower a conversion to a non-interface non-pointer type.
1460 Tuple_type_guard_assignment_statement::lower_to_object_type(Block* b,
1463 source_location loc = this->location();
1465 // var val_temp TYPE
1466 Temporary_statement* val_temp = Statement::make_temporary(this->type_,
1468 b->add_statement(val_temp);
1470 // func FNNAME(*descriptor, interface, *T) bool
1471 source_location bloc = BUILTINS_LOCATION;
1472 Typed_identifier_list* param_types = new Typed_identifier_list();
1473 param_types->push_back(Typed_identifier("inter",
1474 Type::make_type_descriptor_ptr_type(),
1476 param_types->push_back(Typed_identifier("i", this->expr_->type(), bloc));
1477 Type* ptype = Type::make_pointer_type(this->type_);
1478 param_types->push_back(Typed_identifier("v", ptype, bloc));
1479 Typed_identifier_list* ret_types = new Typed_identifier_list();
1480 ret_types->push_back(Typed_identifier("ok", Type::lookup_bool_type(), bloc));
1481 Function_type* fntype = Type::make_function_type(NULL, param_types,
1484 Named_object::make_function_declaration(fnname, NULL, fntype, bloc);
1485 std::string asm_name = "runtime.";
1487 fn->func_declaration_value()->set_asm_name(asm_name);
1489 // ok = FNNAME(type_descriptor, expr, &val_temp)
1490 Expression* func = Expression::make_func_reference(fn, NULL, loc);
1491 Expression_list* params = new Expression_list();
1492 params->push_back(Expression::make_type_descriptor(this->type_, loc));
1493 params->push_back(this->expr_);
1494 Expression* ref = Expression::make_temporary_reference(val_temp, loc);
1495 params->push_back(Expression::make_unary(OPERATOR_AND, ref, loc));
1496 Expression* call = Expression::make_call(func, params, false, loc);
1497 Statement* s = Statement::make_assignment(this->ok_, call, loc);
1498 b->add_statement(s);
1501 ref = Expression::make_temporary_reference(val_temp, loc);
1502 s = Statement::make_assignment(this->val_, ref, loc);
1503 b->add_statement(s);
1506 // Make an assignment from a type guard to a pair of variables.
1509 Statement::make_tuple_type_guard_assignment(Expression* val, Expression* ok,
1510 Expression* expr, Type* type,
1511 source_location location)
1513 return new Tuple_type_guard_assignment_statement(val, ok, expr, type,
1517 // An expression statement.
1519 class Expression_statement : public Statement
1522 Expression_statement(Expression* expr)
1523 : Statement(STATEMENT_EXPRESSION, expr->location()),
1529 do_traverse(Traverse* traverse)
1530 { return this->traverse_expression(traverse, &this->expr_); }
1533 do_determine_types()
1534 { this->expr_->determine_type_no_context(); }
1537 do_may_fall_through() const;
1540 do_get_tree(Translate_context* context)
1541 { return this->expr_->get_tree(context); }
1547 // An expression statement may fall through unless it is a call to a
1548 // function which does not return.
1551 Expression_statement::do_may_fall_through() const
1553 const Call_expression* call = this->expr_->call_expression();
1556 const Expression* fn = call->fn();
1557 const Func_expression* fe = fn->func_expression();
1560 const Named_object* no = fe->named_object();
1562 Function_type* fntype;
1563 if (no->is_function())
1564 fntype = no->func_value()->type();
1565 else if (no->is_function_declaration())
1566 fntype = no->func_declaration_value()->type();
1570 // The builtin function panic does not return.
1571 if (fntype != NULL && fntype->is_builtin() && no->name() == "panic")
1578 // Make an expression statement from an Expression.
1581 Statement::make_statement(Expression* expr)
1583 return new Expression_statement(expr);
1586 // A block statement--a list of statements which may include variable
1589 class Block_statement : public Statement
1592 Block_statement(Block* block, source_location location)
1593 : Statement(STATEMENT_BLOCK, location),
1599 do_traverse(Traverse* traverse)
1600 { return this->block_->traverse(traverse); }
1603 do_determine_types()
1604 { this->block_->determine_types(); }
1607 do_may_fall_through() const
1608 { return this->block_->may_fall_through(); }
1611 do_get_tree(Translate_context* context)
1612 { return this->block_->get_tree(context); }
1618 // Make a block statement.
1621 Statement::make_block_statement(Block* block, source_location location)
1623 return new Block_statement(block, location);
1626 // An increment or decrement statement.
1628 class Inc_dec_statement : public Statement
1631 Inc_dec_statement(bool is_inc, Expression* expr)
1632 : Statement(STATEMENT_INCDEC, expr->location()),
1633 expr_(expr), is_inc_(is_inc)
1638 do_traverse(Traverse* traverse)
1639 { return this->traverse_expression(traverse, &this->expr_); }
1642 do_traverse_assignments(Traverse_assignments*)
1643 { gcc_unreachable(); }
1646 do_lower(Gogo*, Block*);
1649 do_get_tree(Translate_context*)
1650 { gcc_unreachable(); }
1653 // The l-value to increment or decrement.
1655 // Whether to increment or decrement.
1659 // Lower to += or -=.
1662 Inc_dec_statement::do_lower(Gogo*, Block*)
1664 source_location loc = this->location();
1667 mpz_init_set_ui(oval, 1UL);
1668 Expression* oexpr = Expression::make_integer(&oval, NULL, loc);
1671 Operator op = this->is_inc_ ? OPERATOR_PLUSEQ : OPERATOR_MINUSEQ;
1672 return Statement::make_assignment_operation(op, this->expr_, oexpr, loc);
1675 // Make an increment statement.
1678 Statement::make_inc_statement(Expression* expr)
1680 return new Inc_dec_statement(true, expr);
1683 // Make a decrement statement.
1686 Statement::make_dec_statement(Expression* expr)
1688 return new Inc_dec_statement(false, expr);
1691 // Class Thunk_statement. This is the base class for go and defer
1694 const char* const Thunk_statement::thunk_field_fn = "fn";
1696 const char* const Thunk_statement::thunk_field_receiver = "receiver";
1700 Thunk_statement::Thunk_statement(Statement_classification classification,
1701 Call_expression* call,
1702 source_location location)
1703 : Statement(classification, location),
1704 call_(call), struct_type_(NULL)
1708 // Return whether this is a simple statement which does not require a
1712 Thunk_statement::is_simple(Function_type* fntype) const
1714 // We need a thunk to call a method, or to pass a variable number of
1716 if (fntype->is_method() || fntype->is_varargs())
1719 // A defer statement requires a thunk to set up for whether the
1720 // function can call recover.
1721 if (this->classification() == STATEMENT_DEFER)
1724 // We can only permit a single parameter of pointer type.
1725 const Typed_identifier_list* parameters = fntype->parameters();
1726 if (parameters != NULL
1727 && (parameters->size() > 1
1728 || (parameters->size() == 1
1729 && parameters->begin()->type()->points_to() == NULL)))
1732 // If the function returns multiple values, or returns a type other
1733 // than integer, floating point, or pointer, then it may get a
1734 // hidden first parameter, in which case we need the more
1735 // complicated approach. This is true even though we are going to
1736 // ignore the return value.
1737 const Typed_identifier_list* results = fntype->results();
1739 && (results->size() > 1
1740 || (results->size() == 1
1741 && !results->begin()->type()->is_basic_type()
1742 && results->begin()->type()->points_to() == NULL)))
1745 // If this calls something which is not a simple function, then we
1747 Expression* fn = this->call_->call_expression()->fn();
1748 if (fn->bound_method_expression() != NULL
1749 || fn->interface_field_reference_expression() != NULL)
1755 // Traverse a thunk statement.
1758 Thunk_statement::do_traverse(Traverse* traverse)
1760 return this->traverse_expression(traverse, &this->call_);
1763 // We implement traverse_assignment for a thunk statement because it
1764 // effectively copies the function call.
1767 Thunk_statement::do_traverse_assignments(Traverse_assignments* tassign)
1769 Expression* fn = this->call_->call_expression()->fn();
1770 Expression* fn2 = fn;
1771 tassign->value(&fn2, true, false);
1775 // Determine types in a thunk statement.
1778 Thunk_statement::do_determine_types()
1780 this->call_->determine_type_no_context();
1782 // Now that we know the types of the call, build the struct used to
1784 Call_expression* ce = this->call_->call_expression();
1787 Function_type* fntype = ce->get_function_type();
1788 if (fntype != NULL && !this->is_simple(fntype))
1789 this->struct_type_ = this->build_struct(fntype);
1792 // Check types in a thunk statement.
1795 Thunk_statement::do_check_types(Gogo*)
1797 Call_expression* ce = this->call_->call_expression();
1800 if (!this->call_->is_error_expression())
1801 this->report_error("expected call expression");
1804 Function_type* fntype = ce->get_function_type();
1805 if (fntype != NULL && fntype->is_method())
1807 Expression* fn = ce->fn();
1808 if (fn->bound_method_expression() == NULL
1809 && fn->interface_field_reference_expression() == NULL)
1810 this->report_error(_("no object for method call"));
1814 // The Traverse class used to find and simplify thunk statements.
1816 class Simplify_thunk_traverse : public Traverse
1819 Simplify_thunk_traverse(Gogo* gogo)
1820 : Traverse(traverse_blocks),
1832 Simplify_thunk_traverse::block(Block* b)
1834 // The parser ensures that thunk statements always appear at the end
1836 if (b->statements()->size() < 1)
1837 return TRAVERSE_CONTINUE;
1838 Thunk_statement* stat = b->statements()->back()->thunk_statement();
1840 return TRAVERSE_CONTINUE;
1841 if (stat->simplify_statement(this->gogo_, b))
1842 return TRAVERSE_SKIP_COMPONENTS;
1843 return TRAVERSE_CONTINUE;
1846 // Simplify all thunk statements.
1849 Gogo::simplify_thunk_statements()
1851 Simplify_thunk_traverse thunk_traverse(this);
1852 this->traverse(&thunk_traverse);
1855 // Simplify complex thunk statements into simple ones. A complicated
1856 // thunk statement is one which takes anything other than zero
1857 // parameters or a single pointer parameter. We rewrite it into code
1858 // which allocates a struct, stores the parameter values into the
1859 // struct, and does a simple go or defer statement which passes the
1860 // struct to a thunk. The thunk does the real call.
1863 Thunk_statement::simplify_statement(Gogo* gogo, Block* block)
1865 if (this->classification() == STATEMENT_ERROR)
1867 if (this->call_->is_error_expression())
1870 Call_expression* ce = this->call_->call_expression();
1871 Function_type* fntype = ce->get_function_type();
1874 gcc_assert(saw_errors());
1875 this->set_is_error();
1878 if (this->is_simple(fntype))
1881 Expression* fn = ce->fn();
1882 Bound_method_expression* bound_method = fn->bound_method_expression();
1883 Interface_field_reference_expression* interface_method =
1884 fn->interface_field_reference_expression();
1885 const bool is_method = bound_method != NULL || interface_method != NULL;
1887 source_location location = this->location();
1889 std::string thunk_name = Gogo::thunk_name();
1892 this->build_thunk(gogo, thunk_name, fntype);
1894 // Generate code to call the thunk.
1896 // Get the values to store into the struct which is the single
1897 // argument to the thunk.
1899 Expression_list* vals = new Expression_list();
1900 if (fntype->is_builtin())
1902 else if (!is_method)
1903 vals->push_back(fn);
1904 else if (interface_method != NULL)
1905 vals->push_back(interface_method->expr());
1906 else if (bound_method != NULL)
1908 vals->push_back(bound_method->method());
1909 Expression* first_arg = bound_method->first_argument();
1911 // We always pass a pointer when calling a method.
1912 if (first_arg->type()->points_to() == NULL)
1913 first_arg = Expression::make_unary(OPERATOR_AND, first_arg, location);
1915 // If we are calling a method which was inherited from an
1916 // embedded struct, and the method did not get a stub, then the
1917 // first type may be wrong.
1918 Type* fatype = bound_method->first_argument_type();
1921 if (fatype->points_to() == NULL)
1922 fatype = Type::make_pointer_type(fatype);
1923 Type* unsafe = Type::make_pointer_type(Type::make_void_type());
1924 first_arg = Expression::make_cast(unsafe, first_arg, location);
1925 first_arg = Expression::make_cast(fatype, first_arg, location);
1928 vals->push_back(first_arg);
1933 if (ce->args() != NULL)
1935 for (Expression_list::const_iterator p = ce->args()->begin();
1936 p != ce->args()->end();
1938 vals->push_back(*p);
1941 // Build the struct.
1942 Expression* constructor =
1943 Expression::make_struct_composite_literal(this->struct_type_, vals,
1946 // Allocate the initialized struct on the heap.
1947 constructor = Expression::make_heap_composite(constructor, location);
1949 // Look up the thunk.
1950 Named_object* named_thunk = gogo->lookup(thunk_name, NULL);
1951 gcc_assert(named_thunk != NULL && named_thunk->is_function());
1954 Expression* func = Expression::make_func_reference(named_thunk, NULL,
1956 Expression_list* params = new Expression_list();
1957 params->push_back(constructor);
1958 Call_expression* call = Expression::make_call(func, params, false, location);
1960 // Build the simple go or defer statement.
1962 if (this->classification() == STATEMENT_GO)
1963 s = Statement::make_go_statement(call, location);
1964 else if (this->classification() == STATEMENT_DEFER)
1965 s = Statement::make_defer_statement(call, location);
1969 // The current block should end with the go statement.
1970 gcc_assert(block->statements()->size() >= 1);
1971 gcc_assert(block->statements()->back() == this);
1972 block->replace_statement(block->statements()->size() - 1, s);
1974 // We already ran the determine_types pass, so we need to run it now
1975 // for the new statement.
1976 s->determine_types();
1979 gogo->check_types_in_block(block);
1981 // Return true to tell the block not to keep looking at statements.
1985 // Set the name to use for thunk parameter N.
1988 Thunk_statement::thunk_field_param(int n, char* buf, size_t buflen)
1990 snprintf(buf, buflen, "a%d", n);
1993 // Build a new struct type to hold the parameters for a complicated
1994 // thunk statement. FNTYPE is the type of the function call.
1997 Thunk_statement::build_struct(Function_type* fntype)
1999 source_location location = this->location();
2001 Struct_field_list* fields = new Struct_field_list();
2003 Call_expression* ce = this->call_->call_expression();
2004 Expression* fn = ce->fn();
2006 Interface_field_reference_expression* interface_method =
2007 fn->interface_field_reference_expression();
2008 if (interface_method != NULL)
2010 // If this thunk statement calls a method on an interface, we
2011 // pass the interface object to the thunk.
2012 Typed_identifier tid(Thunk_statement::thunk_field_fn,
2013 interface_method->expr()->type(),
2015 fields->push_back(Struct_field(tid));
2017 else if (!fntype->is_builtin())
2019 // The function to call.
2020 Typed_identifier tid(Go_statement::thunk_field_fn, fntype, location);
2021 fields->push_back(Struct_field(tid));
2023 else if (ce->is_recover_call())
2025 // The predeclared recover function has no argument. However,
2026 // we add an argument when building recover thunks. Handle that
2028 fields->push_back(Struct_field(Typed_identifier("can_recover",
2029 Type::lookup_bool_type(),
2033 if (fn->bound_method_expression() != NULL)
2035 gcc_assert(fntype->is_method());
2036 Type* rtype = fntype->receiver()->type();
2037 // We always pass the receiver as a pointer.
2038 if (rtype->points_to() == NULL)
2039 rtype = Type::make_pointer_type(rtype);
2040 Typed_identifier tid(Thunk_statement::thunk_field_receiver, rtype,
2042 fields->push_back(Struct_field(tid));
2045 const Expression_list* args = ce->args();
2049 for (Expression_list::const_iterator p = args->begin();
2054 this->thunk_field_param(i, buf, sizeof buf);
2055 fields->push_back(Struct_field(Typed_identifier(buf, (*p)->type(),
2060 return Type::make_struct_type(fields, location);
2063 // Build the thunk we are going to call. This is a brand new, albeit
2064 // artificial, function.
2067 Thunk_statement::build_thunk(Gogo* gogo, const std::string& thunk_name,
2068 Function_type* fntype)
2070 source_location location = this->location();
2072 Call_expression* ce = this->call_->call_expression();
2074 bool may_call_recover = false;
2075 if (this->classification() == STATEMENT_DEFER)
2077 Func_expression* fn = ce->fn()->func_expression();
2079 may_call_recover = true;
2082 const Named_object* no = fn->named_object();
2083 if (!no->is_function())
2084 may_call_recover = true;
2086 may_call_recover = no->func_value()->calls_recover();
2090 // Build the type of the thunk. The thunk takes a single parameter,
2091 // which is a pointer to the special structure we build.
2092 const char* const parameter_name = "__go_thunk_parameter";
2093 Typed_identifier_list* thunk_parameters = new Typed_identifier_list();
2094 Type* pointer_to_struct_type = Type::make_pointer_type(this->struct_type_);
2095 thunk_parameters->push_back(Typed_identifier(parameter_name,
2096 pointer_to_struct_type,
2099 Typed_identifier_list* thunk_results = NULL;
2100 if (may_call_recover)
2102 // When deferring a function which may call recover, add a
2103 // return value, to disable tail call optimizations which will
2104 // break the way we check whether recover is permitted.
2105 thunk_results = new Typed_identifier_list();
2106 thunk_results->push_back(Typed_identifier("", Type::lookup_bool_type(),
2110 Function_type* thunk_type = Type::make_function_type(NULL, thunk_parameters,
2114 // Start building the thunk.
2115 Named_object* function = gogo->start_function(thunk_name, thunk_type, true,
2118 // For a defer statement, start with a call to
2119 // __go_set_defer_retaddr. */
2120 Label* retaddr_label = NULL;
2121 if (may_call_recover)
2123 retaddr_label = gogo->add_label_reference("retaddr");
2124 Expression* arg = Expression::make_label_addr(retaddr_label, location);
2125 Expression_list* args = new Expression_list();
2126 args->push_back(arg);
2128 static Named_object* set_defer_retaddr;
2129 if (set_defer_retaddr == NULL)
2131 const source_location bloc = BUILTINS_LOCATION;
2132 Typed_identifier_list* param_types = new Typed_identifier_list();
2133 Type *voidptr_type = Type::make_pointer_type(Type::make_void_type());
2134 param_types->push_back(Typed_identifier("r", voidptr_type, bloc));
2136 Typed_identifier_list* result_types = new Typed_identifier_list();
2137 result_types->push_back(Typed_identifier("",
2138 Type::lookup_bool_type(),
2141 Function_type* t = Type::make_function_type(NULL, param_types,
2142 result_types, bloc);
2144 Named_object::make_function_declaration("__go_set_defer_retaddr",
2146 const char* n = "__go_set_defer_retaddr";
2147 set_defer_retaddr->func_declaration_value()->set_asm_name(n);
2150 Expression* fn = Expression::make_func_reference(set_defer_retaddr,
2152 Expression* call = Expression::make_call(fn, args, false, location);
2154 // This is a hack to prevent the middle-end from deleting the
2156 gogo->start_block(location);
2157 gogo->add_statement(Statement::make_goto_statement(retaddr_label,
2159 Block* then_block = gogo->finish_block(location);
2160 then_block->determine_types();
2162 Statement* s = Statement::make_if_statement(call, then_block, NULL,
2164 s->determine_types();
2165 gogo->add_statement(s);
2168 // Get a reference to the parameter.
2169 Named_object* named_parameter = gogo->lookup(parameter_name, NULL);
2170 gcc_assert(named_parameter != NULL && named_parameter->is_variable());
2172 // Build the call. Note that the field names are the same as the
2173 // ones used in build_struct.
2174 Expression* thunk_parameter = Expression::make_var_reference(named_parameter,
2176 thunk_parameter = Expression::make_unary(OPERATOR_MULT, thunk_parameter,
2179 Bound_method_expression* bound_method = ce->fn()->bound_method_expression();
2180 Interface_field_reference_expression* interface_method =
2181 ce->fn()->interface_field_reference_expression();
2183 Expression* func_to_call;
2184 unsigned int next_index;
2185 if (!fntype->is_builtin())
2187 func_to_call = Expression::make_field_reference(thunk_parameter,
2193 gcc_assert(bound_method == NULL && interface_method == NULL);
2194 func_to_call = ce->fn();
2198 if (bound_method != NULL)
2200 Expression* r = Expression::make_field_reference(thunk_parameter, 1,
2202 // The main program passes in a function pointer from the
2203 // interface expression, so here we can make a bound method in
2205 func_to_call = Expression::make_bound_method(r, func_to_call,
2209 else if (interface_method != NULL)
2211 // The main program passes the interface object.
2212 const std::string& name(interface_method->name());
2213 func_to_call = Expression::make_interface_field_reference(func_to_call,
2218 Expression_list* call_params = new Expression_list();
2219 const Struct_field_list* fields = this->struct_type_->fields();
2220 Struct_field_list::const_iterator p = fields->begin();
2221 for (unsigned int i = 0; i < next_index; ++i)
2223 bool is_recover_call = ce->is_recover_call();
2224 Expression* recover_arg = NULL;
2225 for (; p != fields->end(); ++p, ++next_index)
2227 Expression* thunk_param = Expression::make_var_reference(named_parameter,
2229 thunk_param = Expression::make_unary(OPERATOR_MULT, thunk_param,
2231 Expression* param = Expression::make_field_reference(thunk_param,
2234 if (!is_recover_call)
2235 call_params->push_back(param);
2238 gcc_assert(call_params->empty());
2239 recover_arg = param;
2243 if (call_params->empty())
2249 Expression* call = Expression::make_call(func_to_call, call_params, false,
2251 // We need to lower in case this is a builtin function.
2252 call = call->lower(gogo, function, -1);
2253 Call_expression* call_ce = call->call_expression();
2254 if (call_ce != NULL && may_call_recover)
2255 call_ce->set_is_deferred();
2257 Statement* call_statement = Statement::make_statement(call);
2259 // We already ran the determine_types pass, so we need to run it
2260 // just for this statement now.
2261 call_statement->determine_types();
2264 call->check_types(gogo);
2266 if (call_ce != NULL && recover_arg != NULL)
2267 call_ce->set_recover_arg(recover_arg);
2269 gogo->add_statement(call_statement);
2271 // If this is a defer statement, the label comes immediately after
2273 if (may_call_recover)
2275 gogo->add_label_definition("retaddr", location);
2277 Expression_list* vals = new Expression_list();
2278 vals->push_back(Expression::make_boolean(false, location));
2279 const Typed_identifier_list* results =
2280 function->func_value()->type()->results();
2281 gogo->add_statement(Statement::make_return_statement(results, vals,
2285 // That is all the thunk has to do.
2286 gogo->finish_function(location);
2289 // Get the function and argument trees.
2292 Thunk_statement::get_fn_and_arg(Translate_context* context, tree* pfn,
2295 if (this->call_->is_error_expression())
2297 *pfn = error_mark_node;
2298 *parg = error_mark_node;
2302 Call_expression* ce = this->call_->call_expression();
2304 Expression* fn = ce->fn();
2305 *pfn = fn->get_tree(context);
2307 const Expression_list* args = ce->args();
2308 if (args == NULL || args->empty())
2309 *parg = null_pointer_node;
2312 gcc_assert(args->size() == 1);
2313 *parg = args->front()->get_tree(context);
2317 // Class Go_statement.
2320 Go_statement::do_get_tree(Translate_context* context)
2324 this->get_fn_and_arg(context, &fn_tree, &arg_tree);
2326 static tree go_fndecl;
2328 tree fn_arg_type = NULL_TREE;
2329 if (go_fndecl == NULL_TREE)
2331 // Only build FN_ARG_TYPE if we need it.
2332 tree subargtypes = tree_cons(NULL_TREE, ptr_type_node, void_list_node);
2333 tree subfntype = build_function_type(ptr_type_node, subargtypes);
2334 fn_arg_type = build_pointer_type(subfntype);
2337 return Gogo::call_builtin(&go_fndecl,
2348 // Make a go statement.
2351 Statement::make_go_statement(Call_expression* call, source_location location)
2353 return new Go_statement(call, location);
2356 // Class Defer_statement.
2359 Defer_statement::do_get_tree(Translate_context* context)
2361 source_location loc = this->location();
2365 this->get_fn_and_arg(context, &fn_tree, &arg_tree);
2366 if (fn_tree == error_mark_node || arg_tree == error_mark_node)
2367 return error_mark_node;
2369 static tree defer_fndecl;
2371 tree fn_arg_type = NULL_TREE;
2372 if (defer_fndecl == NULL_TREE)
2374 // Only build FN_ARG_TYPE if we need it.
2375 tree subargtypes = tree_cons(NULL_TREE, ptr_type_node, void_list_node);
2376 tree subfntype = build_function_type(ptr_type_node, subargtypes);
2377 fn_arg_type = build_pointer_type(subfntype);
2380 tree defer_stack = context->function()->func_value()->defer_stack(loc);
2382 return Gogo::call_builtin(&defer_fndecl,
2395 // Make a defer statement.
2398 Statement::make_defer_statement(Call_expression* call,
2399 source_location location)
2401 return new Defer_statement(call, location);
2404 // Class Return_statement.
2406 // Traverse assignments. We treat each return value as a top level
2407 // RHS in an expression.
2410 Return_statement::do_traverse_assignments(Traverse_assignments* tassign)
2412 Expression_list* vals = this->vals_;
2415 for (Expression_list::iterator p = vals->begin();
2418 tassign->value(&*p, true, true);
2423 // Lower a return statement. If we are returning a function call
2424 // which returns multiple values which match the current function,
2425 // split up the call's results. If the function has named result
2426 // variables, and the return statement lists explicit values, then
2427 // implement it by assigning the values to the result variables and
2428 // changing the statement to not list any values. This lets
2429 // panic/recover work correctly.
2432 Return_statement::do_lower(Gogo*, Block* enclosing)
2434 if (this->vals_ == NULL)
2437 const Typed_identifier_list* results = this->results_;
2438 if (results == NULL || results->empty())
2441 // If the current function has multiple return values, and we are
2442 // returning a single call expression, split up the call expression.
2443 size_t results_count = results->size();
2444 if (results_count > 1
2445 && this->vals_->size() == 1
2446 && this->vals_->front()->call_expression() != NULL)
2448 Call_expression* call = this->vals_->front()->call_expression();
2449 size_t count = results->size();
2450 Expression_list* vals = new Expression_list;
2451 for (size_t i = 0; i < count; ++i)
2452 vals->push_back(Expression::make_call_result(call, i));
2457 if (results->front().name().empty())
2460 if (results_count != this->vals_->size())
2462 // Presumably an error which will be reported in check_types.
2466 // Assign to named return values and then return them.
2468 source_location loc = this->location();
2469 const Block* top = enclosing;
2470 while (top->enclosing() != NULL)
2471 top = top->enclosing();
2473 const Bindings *bindings = top->bindings();
2474 Block* b = new Block(enclosing, loc);
2476 Expression_list* lhs = new Expression_list();
2477 Expression_list* rhs = new Expression_list();
2479 Expression_list::const_iterator pe = this->vals_->begin();
2481 for (Typed_identifier_list::const_iterator pr = results->begin();
2482 pr != results->end();
2485 Named_object* rv = bindings->lookup_local(pr->name());
2486 if (rv == NULL || !rv->is_result_variable())
2488 // Presumably an error.
2495 Expression* e = *pe;
2497 // Check types now so that we give a good error message. The
2498 // result type is known. We determine the expression type
2501 Type *rvtype = rv->result_var_value()->type();
2502 Type_context type_context(rvtype, false);
2503 e->determine_type(&type_context);
2506 if (Type::are_assignable(rvtype, e->type(), &reason))
2508 Expression* ve = Expression::make_var_reference(rv, e->location());
2515 error_at(e->location(), "incompatible type for return value %d", i);
2517 error_at(e->location(),
2518 "incompatible type for return value %d (%s)",
2522 gcc_assert(lhs->size() == rhs->size());
2526 else if (lhs->size() == 1)
2528 b->add_statement(Statement::make_assignment(lhs->front(), rhs->front(),
2534 b->add_statement(Statement::make_tuple_assignment(lhs, rhs, loc));
2536 b->add_statement(Statement::make_return_statement(this->results_, NULL,
2539 return Statement::make_block_statement(b, loc);
2545 Return_statement::do_determine_types()
2547 if (this->vals_ == NULL)
2549 const Typed_identifier_list* results = this->results_;
2551 Typed_identifier_list::const_iterator pt;
2552 if (results != NULL)
2553 pt = results->begin();
2554 for (Expression_list::iterator pe = this->vals_->begin();
2555 pe != this->vals_->end();
2558 if (results == NULL || pt == results->end())
2559 (*pe)->determine_type_no_context();
2562 Type_context context(pt->type(), false);
2563 (*pe)->determine_type(&context);
2572 Return_statement::do_check_types(Gogo*)
2574 if (this->vals_ == NULL)
2577 const Typed_identifier_list* results = this->results_;
2578 if (results == NULL)
2580 this->report_error(_("return with value in function "
2581 "with no return type"));
2586 Typed_identifier_list::const_iterator pt = results->begin();
2587 for (Expression_list::const_iterator pe = this->vals_->begin();
2588 pe != this->vals_->end();
2591 if (pt == results->end())
2593 this->report_error(_("too many values in return statement"));
2597 if (!Type::are_assignable(pt->type(), (*pe)->type(), &reason))
2600 error_at(this->location(),
2601 "incompatible type for return value %d",
2604 error_at(this->location(),
2605 "incompatible type for return value %d (%s)",
2607 this->set_is_error();
2609 else if (pt->type()->is_error_type()
2610 || (*pe)->type()->is_error_type()
2611 || pt->type()->is_undefined()
2612 || (*pe)->type()->is_undefined())
2614 // Make sure we get the error for an undefined type.
2616 (*pe)->type()->base();
2617 this->set_is_error();
2621 if (pt != results->end())
2622 this->report_error(_("not enough values in return statement"));
2625 // Build a RETURN_EXPR tree.
2628 Return_statement::do_get_tree(Translate_context* context)
2630 Function* function = context->function()->func_value();
2631 tree fndecl = function->get_decl();
2632 if (fndecl == error_mark_node || DECL_RESULT(fndecl) == error_mark_node)
2633 return error_mark_node;
2635 const Typed_identifier_list* results = this->results_;
2637 if (this->vals_ == NULL)
2639 tree stmt_list = NULL_TREE;
2640 tree retval = function->return_value(context->gogo(),
2641 context->function(),
2645 if (retval == NULL_TREE)
2647 else if (retval == error_mark_node)
2648 return error_mark_node;
2650 set = fold_build2_loc(this->location(), MODIFY_EXPR, void_type_node,
2651 DECL_RESULT(fndecl), retval);
2652 append_to_statement_list(this->build_stmt_1(RETURN_EXPR, set),
2656 else if (this->vals_->size() == 1)
2658 gcc_assert(!VOID_TYPE_P(TREE_TYPE(TREE_TYPE(fndecl))));
2659 tree val = (*this->vals_->begin())->get_tree(context);
2660 gcc_assert(results != NULL && results->size() == 1);
2661 val = Expression::convert_for_assignment(context,
2662 results->begin()->type(),
2663 (*this->vals_->begin())->type(),
2664 val, this->location());
2665 if (val == error_mark_node)
2666 return error_mark_node;
2667 tree set = build2(MODIFY_EXPR, void_type_node,
2668 DECL_RESULT(fndecl), val);
2669 SET_EXPR_LOCATION(set, this->location());
2670 return this->build_stmt_1(RETURN_EXPR, set);
2674 gcc_assert(!VOID_TYPE_P(TREE_TYPE(TREE_TYPE(fndecl))));
2675 tree stmt_list = NULL_TREE;
2676 tree rettype = TREE_TYPE(DECL_RESULT(fndecl));
2677 tree retvar = create_tmp_var(rettype, "RESULT");
2678 gcc_assert(results != NULL && results->size() == this->vals_->size());
2679 Expression_list::const_iterator pv = this->vals_->begin();
2680 Typed_identifier_list::const_iterator pr = results->begin();
2681 for (tree field = TYPE_FIELDS(rettype);
2683 ++pv, ++pr, field = DECL_CHAIN(field))
2685 gcc_assert(pv != this->vals_->end());
2686 tree val = (*pv)->get_tree(context);
2687 val = Expression::convert_for_assignment(context, pr->type(),
2690 if (val == error_mark_node)
2691 return error_mark_node;
2692 tree set = build2(MODIFY_EXPR, void_type_node,
2693 build3(COMPONENT_REF, TREE_TYPE(field),
2694 retvar, field, NULL_TREE),
2696 SET_EXPR_LOCATION(set, this->location());
2697 append_to_statement_list(set, &stmt_list);
2699 tree set = build2(MODIFY_EXPR, void_type_node, DECL_RESULT(fndecl),
2701 append_to_statement_list(this->build_stmt_1(RETURN_EXPR, set),
2707 // Make a return statement.
2710 Statement::make_return_statement(const Typed_identifier_list* results,
2711 Expression_list* vals,
2712 source_location location)
2714 return new Return_statement(results, vals, location);
2717 // A break or continue statement.
2719 class Bc_statement : public Statement
2722 Bc_statement(bool is_break, Unnamed_label* label, source_location location)
2723 : Statement(STATEMENT_BREAK_OR_CONTINUE, location),
2724 label_(label), is_break_(is_break)
2729 { return this->is_break_; }
2733 do_traverse(Traverse*)
2734 { return TRAVERSE_CONTINUE; }
2737 do_may_fall_through() const
2741 do_get_tree(Translate_context*)
2742 { return this->label_->get_goto(this->location()); }
2745 // The label that this branches to.
2746 Unnamed_label* label_;
2747 // True if this is "break", false if it is "continue".
2751 // Make a break statement.
2754 Statement::make_break_statement(Unnamed_label* label, source_location location)
2756 return new Bc_statement(true, label, location);
2759 // Make a continue statement.
2762 Statement::make_continue_statement(Unnamed_label* label,
2763 source_location location)
2765 return new Bc_statement(false, label, location);
2768 // A goto statement.
2770 class Goto_statement : public Statement
2773 Goto_statement(Label* label, source_location location)
2774 : Statement(STATEMENT_GOTO, location),
2780 do_traverse(Traverse*)
2781 { return TRAVERSE_CONTINUE; }
2784 do_check_types(Gogo*);
2787 do_may_fall_through() const
2791 do_get_tree(Translate_context*);
2797 // Check types for a label. There aren't any types per se, but we use
2798 // this to give an error if the label was never defined.
2801 Goto_statement::do_check_types(Gogo*)
2803 if (!this->label_->is_defined())
2805 error_at(this->location(), "reference to undefined label %qs",
2806 Gogo::message_name(this->label_->name()).c_str());
2807 this->set_is_error();
2811 // Return the tree for the goto statement.
2814 Goto_statement::do_get_tree(Translate_context*)
2816 return this->build_stmt_1(GOTO_EXPR, this->label_->get_decl());
2819 // Make a goto statement.
2822 Statement::make_goto_statement(Label* label, source_location location)
2824 return new Goto_statement(label, location);
2827 // A goto statement to an unnamed label.
2829 class Goto_unnamed_statement : public Statement
2832 Goto_unnamed_statement(Unnamed_label* label, source_location location)
2833 : Statement(STATEMENT_GOTO_UNNAMED, location),
2839 do_traverse(Traverse*)
2840 { return TRAVERSE_CONTINUE; }
2843 do_may_fall_through() const
2847 do_get_tree(Translate_context*)
2848 { return this->label_->get_goto(this->location()); }
2851 Unnamed_label* label_;
2854 // Make a goto statement to an unnamed label.
2857 Statement::make_goto_unnamed_statement(Unnamed_label* label,
2858 source_location location)
2860 return new Goto_unnamed_statement(label, location);
2863 // Class Label_statement.
2868 Label_statement::do_traverse(Traverse*)
2870 return TRAVERSE_CONTINUE;
2873 // Return a tree defining this label.
2876 Label_statement::do_get_tree(Translate_context*)
2878 return this->build_stmt_1(LABEL_EXPR, this->label_->get_decl());
2881 // Make a label statement.
2884 Statement::make_label_statement(Label* label, source_location location)
2886 return new Label_statement(label, location);
2889 // An unnamed label statement.
2891 class Unnamed_label_statement : public Statement
2894 Unnamed_label_statement(Unnamed_label* label)
2895 : Statement(STATEMENT_UNNAMED_LABEL, label->location()),
2901 do_traverse(Traverse*)
2902 { return TRAVERSE_CONTINUE; }
2905 do_get_tree(Translate_context*)
2906 { return this->label_->get_definition(); }
2910 Unnamed_label* label_;
2913 // Make an unnamed label statement.
2916 Statement::make_unnamed_label_statement(Unnamed_label* label)
2918 return new Unnamed_label_statement(label);
2923 class If_statement : public Statement
2926 If_statement(Expression* cond, Block* then_block, Block* else_block,
2927 source_location location)
2928 : Statement(STATEMENT_IF, location),
2929 cond_(cond), then_block_(then_block), else_block_(else_block)
2934 do_traverse(Traverse*);
2937 do_determine_types();
2940 do_check_types(Gogo*);
2943 do_may_fall_through() const;
2946 do_get_tree(Translate_context*);
2957 If_statement::do_traverse(Traverse* traverse)
2959 if (this->cond_ != NULL)
2961 if (this->traverse_expression(traverse, &this->cond_) == TRAVERSE_EXIT)
2962 return TRAVERSE_EXIT;
2964 if (this->then_block_->traverse(traverse) == TRAVERSE_EXIT)
2965 return TRAVERSE_EXIT;
2966 if (this->else_block_ != NULL)
2968 if (this->else_block_->traverse(traverse) == TRAVERSE_EXIT)
2969 return TRAVERSE_EXIT;
2971 return TRAVERSE_CONTINUE;
2975 If_statement::do_determine_types()
2977 if (this->cond_ != NULL)
2979 Type_context context(Type::lookup_bool_type(), false);
2980 this->cond_->determine_type(&context);
2982 this->then_block_->determine_types();
2983 if (this->else_block_ != NULL)
2984 this->else_block_->determine_types();
2990 If_statement::do_check_types(Gogo*)
2992 if (this->cond_ != NULL)
2994 Type* type = this->cond_->type();
2995 if (type->is_error_type())
2996 this->set_is_error();
2997 else if (!type->is_boolean_type())
2998 this->report_error(_("expected boolean expression"));
3002 // Whether the overall statement may fall through.
3005 If_statement::do_may_fall_through() const
3007 return (this->else_block_ == NULL
3008 || this->then_block_->may_fall_through()
3009 || this->else_block_->may_fall_through());
3015 If_statement::do_get_tree(Translate_context* context)
3017 gcc_assert(this->cond_ == NULL
3018 || this->cond_->type()->is_boolean_type()
3019 || this->cond_->type()->is_error_type());
3020 tree cond_tree = (this->cond_ == NULL
3022 : this->cond_->get_tree(context));
3023 tree then_tree = this->then_block_->get_tree(context);
3024 tree else_tree = (this->else_block_ == NULL
3026 : this->else_block_->get_tree(context));
3027 if (cond_tree == error_mark_node
3028 || then_tree == error_mark_node
3029 || else_tree == error_mark_node)
3030 return error_mark_node;
3031 tree ret = build3(COND_EXPR, void_type_node, cond_tree, then_tree,
3033 SET_EXPR_LOCATION(ret, this->location());
3037 // Make an if statement.
3040 Statement::make_if_statement(Expression* cond, Block* then_block,
3041 Block* else_block, source_location location)
3043 return new If_statement(cond, then_block, else_block, location);
3046 // Class Case_clauses::Case_clause.
3051 Case_clauses::Case_clause::traverse(Traverse* traverse)
3053 if (this->cases_ != NULL
3054 && (traverse->traverse_mask()
3055 & (Traverse::traverse_types | Traverse::traverse_expressions)) != 0)
3057 if (this->cases_->traverse(traverse) == TRAVERSE_EXIT)
3058 return TRAVERSE_EXIT;
3060 if (this->statements_ != NULL)
3062 if (this->statements_->traverse(traverse) == TRAVERSE_EXIT)
3063 return TRAVERSE_EXIT;
3065 return TRAVERSE_CONTINUE;
3068 // Check whether all the case expressions are integer constants.
3071 Case_clauses::Case_clause::is_constant() const
3073 if (this->cases_ != NULL)
3075 for (Expression_list::const_iterator p = this->cases_->begin();
3076 p != this->cases_->end();
3078 if (!(*p)->is_constant() || (*p)->type()->integer_type() == NULL)
3084 // Lower a case clause for a nonconstant switch. VAL_TEMP is the
3085 // value we are switching on; it may be NULL. If START_LABEL is not
3086 // NULL, it goes at the start of the statements, after the condition
3087 // test. We branch to FINISH_LABEL at the end of the statements.
3090 Case_clauses::Case_clause::lower(Block* b, Temporary_statement* val_temp,
3091 Unnamed_label* start_label,
3092 Unnamed_label* finish_label) const
3094 source_location loc = this->location_;
3095 Unnamed_label* next_case_label;
3096 if (this->cases_ == NULL || this->cases_->empty())
3098 gcc_assert(this->is_default_);
3099 next_case_label = NULL;
3103 Expression* cond = NULL;
3105 for (Expression_list::const_iterator p = this->cases_->begin();
3106 p != this->cases_->end();
3109 Expression* this_cond;
3110 if (val_temp == NULL)
3114 Expression* ref = Expression::make_temporary_reference(val_temp,
3116 this_cond = Expression::make_binary(OPERATOR_EQEQ, ref, *p, loc);
3122 cond = Expression::make_binary(OPERATOR_OROR, cond, this_cond, loc);
3125 Block* then_block = new Block(b, loc);
3126 next_case_label = new Unnamed_label(UNKNOWN_LOCATION);
3127 Statement* s = Statement::make_goto_unnamed_statement(next_case_label,
3129 then_block->add_statement(s);
3131 // if !COND { goto NEXT_CASE_LABEL }
3132 cond = Expression::make_unary(OPERATOR_NOT, cond, loc);
3133 s = Statement::make_if_statement(cond, then_block, NULL, loc);
3134 b->add_statement(s);
3137 if (start_label != NULL)
3138 b->add_statement(Statement::make_unnamed_label_statement(start_label));
3140 if (this->statements_ != NULL)
3141 b->add_statement(Statement::make_block_statement(this->statements_, loc));
3143 Statement* s = Statement::make_goto_unnamed_statement(finish_label, loc);
3144 b->add_statement(s);
3146 if (next_case_label != NULL)
3147 b->add_statement(Statement::make_unnamed_label_statement(next_case_label));
3153 Case_clauses::Case_clause::determine_types(Type* type)
3155 if (this->cases_ != NULL)
3157 Type_context case_context(type, false);
3158 for (Expression_list::iterator p = this->cases_->begin();
3159 p != this->cases_->end();
3161 (*p)->determine_type(&case_context);
3163 if (this->statements_ != NULL)
3164 this->statements_->determine_types();
3167 // Check types. Returns false if there was an error.
3170 Case_clauses::Case_clause::check_types(Type* type)
3172 if (this->cases_ != NULL)
3174 for (Expression_list::iterator p = this->cases_->begin();
3175 p != this->cases_->end();
3178 if (!Type::are_assignable(type, (*p)->type(), NULL)
3179 && !Type::are_assignable((*p)->type(), type, NULL))
3181 error_at((*p)->location(),
3182 "type mismatch between switch value and case clause");
3190 // Return true if this clause may fall through to the following
3191 // statements. Note that this is not the same as whether the case
3192 // uses the "fallthrough" keyword.
3195 Case_clauses::Case_clause::may_fall_through() const
3197 if (this->statements_ == NULL)
3199 return this->statements_->may_fall_through();
3202 // Build up the body of a SWITCH_EXPR.
3205 Case_clauses::Case_clause::get_constant_tree(Translate_context* context,
3206 Unnamed_label* break_label,
3207 Case_constants* case_constants,
3208 tree* stmt_list) const
3210 if (this->cases_ != NULL)
3212 for (Expression_list::const_iterator p = this->cases_->begin();
3213 p != this->cases_->end();
3219 if (!(*p)->integer_constant_value(true, ival, &itype))
3221 // Something went wrong. This can happen with a
3222 // negative constant and an unsigned switch value.
3223 gcc_assert(saw_errors());
3226 gcc_assert(itype != NULL);
3227 tree type_tree = itype->get_tree(context->gogo());
3228 tree val = Expression::integer_constant_tree(ival, type_tree);
3231 if (val != error_mark_node)
3233 gcc_assert(TREE_CODE(val) == INTEGER_CST);
3235 std::pair<Case_constants::iterator, bool> ins =
3236 case_constants->insert(val);
3239 // Value was already present.
3240 warning_at(this->location_, 0,
3241 "duplicate case value will never match");
3245 tree label = create_artificial_label(this->location_);
3246 append_to_statement_list(build3(CASE_LABEL_EXPR, void_type_node,
3247 val, NULL_TREE, label),
3253 if (this->is_default_)
3255 tree label = create_artificial_label(this->location_);
3256 append_to_statement_list(build3(CASE_LABEL_EXPR, void_type_node,
3257 NULL_TREE, NULL_TREE, label),
3261 if (this->statements_ != NULL)
3263 tree block_tree = this->statements_->get_tree(context);
3264 if (block_tree != error_mark_node)
3265 append_to_statement_list(block_tree, stmt_list);
3268 if (!this->is_fallthrough_)
3269 append_to_statement_list(break_label->get_goto(this->location_), stmt_list);
3272 // Class Case_clauses.
3277 Case_clauses::traverse(Traverse* traverse)
3279 for (Clauses::iterator p = this->clauses_.begin();
3280 p != this->clauses_.end();
3283 if (p->traverse(traverse) == TRAVERSE_EXIT)
3284 return TRAVERSE_EXIT;
3286 return TRAVERSE_CONTINUE;
3289 // Check whether all the case expressions are constant.
3292 Case_clauses::is_constant() const
3294 for (Clauses::const_iterator p = this->clauses_.begin();
3295 p != this->clauses_.end();
3297 if (!p->is_constant())
3302 // Lower case clauses for a nonconstant switch.
3305 Case_clauses::lower(Block* b, Temporary_statement* val_temp,
3306 Unnamed_label* break_label) const
3308 // The default case.
3309 const Case_clause* default_case = NULL;
3311 // The label for the fallthrough of the previous case.
3312 Unnamed_label* last_fallthrough_label = NULL;
3314 // The label for the start of the default case. This is used if the
3315 // case before the default case falls through.
3316 Unnamed_label* default_start_label = NULL;
3318 // The label for the end of the default case. This normally winds
3319 // up as BREAK_LABEL, but it will be different if the default case
3321 Unnamed_label* default_finish_label = NULL;
3323 for (Clauses::const_iterator p = this->clauses_.begin();
3324 p != this->clauses_.end();
3327 // The label to use for the start of the statements for this
3328 // case. This is NULL unless the previous case falls through.
3329 Unnamed_label* start_label = last_fallthrough_label;
3331 // The label to jump to after the end of the statements for this
3333 Unnamed_label* finish_label = break_label;
3335 last_fallthrough_label = NULL;
3336 if (p->is_fallthrough() && p + 1 != this->clauses_.end())
3338 finish_label = new Unnamed_label(p->location());
3339 last_fallthrough_label = finish_label;
3342 if (!p->is_default())
3343 p->lower(b, val_temp, start_label, finish_label);
3346 // We have to move the default case to the end, so that we
3347 // only use it if all the other tests fail.
3349 default_start_label = start_label;
3350 default_finish_label = finish_label;
3354 if (default_case != NULL)
3355 default_case->lower(b, val_temp, default_start_label,
3356 default_finish_label);
3363 Case_clauses::determine_types(Type* type)
3365 for (Clauses::iterator p = this->clauses_.begin();
3366 p != this->clauses_.end();
3368 p->determine_types(type);
3371 // Check types. Returns false if there was an error.
3374 Case_clauses::check_types(Type* type)
3377 for (Clauses::iterator p = this->clauses_.begin();
3378 p != this->clauses_.end();
3381 if (!p->check_types(type))
3387 // Return true if these clauses may fall through to the statements
3388 // following the switch statement.
3391 Case_clauses::may_fall_through() const
3393 bool found_default = false;
3394 for (Clauses::const_iterator p = this->clauses_.begin();
3395 p != this->clauses_.end();
3398 if (p->may_fall_through() && !p->is_fallthrough())
3400 if (p->is_default())
3401 found_default = true;
3403 return !found_default;
3406 // Return a tree when all case expressions are constants.
3409 Case_clauses::get_constant_tree(Translate_context* context,
3410 Unnamed_label* break_label) const
3412 Case_constants case_constants;
3413 tree stmt_list = NULL_TREE;
3414 for (Clauses::const_iterator p = this->clauses_.begin();
3415 p != this->clauses_.end();
3417 p->get_constant_tree(context, break_label, &case_constants,
3422 // A constant switch statement. A Switch_statement is lowered to this
3423 // when all the cases are constants.
3425 class Constant_switch_statement : public Statement
3428 Constant_switch_statement(Expression* val, Case_clauses* clauses,
3429 Unnamed_label* break_label,
3430 source_location location)
3431 : Statement(STATEMENT_CONSTANT_SWITCH, location),
3432 val_(val), clauses_(clauses), break_label_(break_label)
3437 do_traverse(Traverse*);
3440 do_determine_types();
3443 do_check_types(Gogo*);
3446 do_may_fall_through() const;
3449 do_get_tree(Translate_context*);
3452 // The value to switch on.
3454 // The case clauses.
3455 Case_clauses* clauses_;
3456 // The break label, if needed.
3457 Unnamed_label* break_label_;
3463 Constant_switch_statement::do_traverse(Traverse* traverse)
3465 if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT)
3466 return TRAVERSE_EXIT;
3467 return this->clauses_->traverse(traverse);
3473 Constant_switch_statement::do_determine_types()
3475 this->val_->determine_type_no_context();
3476 this->clauses_->determine_types(this->val_->type());
3482 Constant_switch_statement::do_check_types(Gogo*)
3484 if (!this->clauses_->check_types(this->val_->type()))
3485 this->set_is_error();
3488 // Return whether this switch may fall through.
3491 Constant_switch_statement::do_may_fall_through() const
3493 if (this->clauses_ == NULL)
3496 // If we have a break label, then some case needed it. That implies
3497 // that the switch statement as a whole can fall through.
3498 if (this->break_label_ != NULL)
3501 return this->clauses_->may_fall_through();
3504 // Convert to GENERIC.
3507 Constant_switch_statement::do_get_tree(Translate_context* context)
3509 tree switch_val_tree = this->val_->get_tree(context);
3511 Unnamed_label* break_label = this->break_label_;
3512 if (break_label == NULL)
3513 break_label = new Unnamed_label(this->location());
3515 tree stmt_list = NULL_TREE;
3516 tree s = build3(SWITCH_EXPR, void_type_node, switch_val_tree,
3517 this->clauses_->get_constant_tree(context, break_label),
3519 SET_EXPR_LOCATION(s, this->location());
3520 append_to_statement_list(s, &stmt_list);
3522 append_to_statement_list(break_label->get_definition(), &stmt_list);
3527 // Class Switch_statement.
3532 Switch_statement::do_traverse(Traverse* traverse)
3534 if (this->val_ != NULL)
3536 if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT)
3537 return TRAVERSE_EXIT;
3539 return this->clauses_->traverse(traverse);
3542 // Lower a Switch_statement to a Constant_switch_statement or a series
3543 // of if statements.
3546 Switch_statement::do_lower(Gogo*, Block* enclosing)
3548 source_location loc = this->location();
3550 if (this->val_ != NULL
3551 && (this->val_->is_error_expression()
3552 || this->val_->type()->is_error_type()))
3553 return Statement::make_error_statement(loc);
3555 if (this->val_ != NULL
3556 && this->val_->type()->integer_type() != NULL
3557 && !this->clauses_->empty()
3558 && this->clauses_->is_constant())
3559 return new Constant_switch_statement(this->val_, this->clauses_,
3560 this->break_label_, loc);
3562 Block* b = new Block(enclosing, loc);
3564 if (this->clauses_->empty())
3566 Expression* val = this->val_;
3568 val = Expression::make_boolean(true, loc);
3569 return Statement::make_statement(val);
3572 Temporary_statement* val_temp;
3573 if (this->val_ == NULL)
3577 // var val_temp VAL_TYPE = VAL
3578 val_temp = Statement::make_temporary(NULL, this->val_, loc);
3579 b->add_statement(val_temp);
3582 this->clauses_->lower(b, val_temp, this->break_label());
3584 Statement* s = Statement::make_unnamed_label_statement(this->break_label_);
3585 b->add_statement(s);
3587 return Statement::make_block_statement(b, loc);
3590 // Return the break label for this switch statement, creating it if
3594 Switch_statement::break_label()
3596 if (this->break_label_ == NULL)
3597 this->break_label_ = new Unnamed_label(this->location());
3598 return this->break_label_;
3601 // Make a switch statement.
3604 Statement::make_switch_statement(Expression* val, source_location location)
3606 return new Switch_statement(val, location);
3609 // Class Type_case_clauses::Type_case_clause.
3614 Type_case_clauses::Type_case_clause::traverse(Traverse* traverse)
3616 if (!this->is_default_
3617 && ((traverse->traverse_mask()
3618 & (Traverse::traverse_types | Traverse::traverse_expressions)) != 0)
3619 && Type::traverse(this->type_, traverse) == TRAVERSE_EXIT)
3620 return TRAVERSE_EXIT;
3621 if (this->statements_ != NULL)
3622 return this->statements_->traverse(traverse);
3623 return TRAVERSE_CONTINUE;
3626 // Lower one clause in a type switch. Add statements to the block B.
3627 // The type descriptor we are switching on is in DESCRIPTOR_TEMP.
3628 // BREAK_LABEL is the label at the end of the type switch.
3629 // *STMTS_LABEL, if not NULL, is a label to put at the start of the
3633 Type_case_clauses::Type_case_clause::lower(Block* b,
3634 Temporary_statement* descriptor_temp,
3635 Unnamed_label* break_label,
3636 Unnamed_label** stmts_label) const
3638 source_location loc = this->location_;
3640 Unnamed_label* next_case_label = NULL;
3641 if (!this->is_default_)
3643 Type* type = this->type_;
3646 // The language permits case nil, which is of course a constant
3647 // rather than a type. It will appear here as an invalid
3649 if (type->is_nil_constant_as_type())
3652 Expression::make_temporary_reference(descriptor_temp, loc);
3653 cond = Expression::make_binary(OPERATOR_EQEQ, ref,
3654 Expression::make_nil(loc),
3660 if (type->interface_type() == NULL)
3662 // func ifacetypeeq(*descriptor, *descriptor) bool
3663 static Named_object* ifacetypeeq;
3664 if (ifacetypeeq == NULL)
3666 const source_location bloc = BUILTINS_LOCATION;
3667 Typed_identifier_list* param_types =
3668 new Typed_identifier_list();
3669 Type* descriptor_type = Type::make_type_descriptor_ptr_type();
3670 param_types->push_back(Typed_identifier("a", descriptor_type,
3672 param_types->push_back(Typed_identifier("b", descriptor_type,
3674 Typed_identifier_list* ret_types =
3675 new Typed_identifier_list();
3676 Type* bool_type = Type::lookup_bool_type();
3677 ret_types->push_back(Typed_identifier("", bool_type, bloc));
3678 Function_type* fntype = Type::make_function_type(NULL,
3683 Named_object::make_function_declaration("ifacetypeeq", NULL,
3685 const char* n = "runtime.ifacetypeeq";
3686 ifacetypeeq->func_declaration_value()->set_asm_name(n);
3689 // ifacetypeeq(descriptor_temp, DESCRIPTOR)
3690 func = Expression::make_func_reference(ifacetypeeq, NULL, loc);
3694 // func ifaceI2Tp(*descriptor, *descriptor) bool
3695 static Named_object* ifaceI2Tp;
3696 if (ifaceI2Tp == NULL)
3698 const source_location bloc = BUILTINS_LOCATION;
3699 Typed_identifier_list* param_types =
3700 new Typed_identifier_list();
3701 Type* descriptor_type = Type::make_type_descriptor_ptr_type();
3702 param_types->push_back(Typed_identifier("a", descriptor_type,
3704 param_types->push_back(Typed_identifier("b", descriptor_type,
3706 Typed_identifier_list* ret_types =
3707 new Typed_identifier_list();
3708 Type* bool_type = Type::lookup_bool_type();
3709 ret_types->push_back(Typed_identifier("", bool_type, bloc));
3710 Function_type* fntype = Type::make_function_type(NULL,
3715 Named_object::make_function_declaration("ifaceI2Tp", NULL,
3717 const char* n = "runtime.ifaceI2Tp";
3718 ifaceI2Tp->func_declaration_value()->set_asm_name(n);
3721 // ifaceI2Tp(descriptor_temp, DESCRIPTOR)
3722 func = Expression::make_func_reference(ifaceI2Tp, NULL, loc);
3724 Expression_list* params = new Expression_list();
3725 params->push_back(Expression::make_type_descriptor(type, loc));
3727 Expression::make_temporary_reference(descriptor_temp, loc);
3728 params->push_back(ref);
3729 cond = Expression::make_call(func, params, false, loc);
3732 Unnamed_label* dest;
3733 if (!this->is_fallthrough_)
3735 // if !COND { goto NEXT_CASE_LABEL }
3736 next_case_label = new Unnamed_label(UNKNOWN_LOCATION);
3737 dest = next_case_label;
3738 cond = Expression::make_unary(OPERATOR_NOT, cond, loc);
3742 // if COND { goto STMTS_LABEL }
3743 gcc_assert(stmts_label != NULL);
3744 if (*stmts_label == NULL)
3745 *stmts_label = new Unnamed_label(UNKNOWN_LOCATION);
3746 dest = *stmts_label;
3748 Block* then_block = new Block(b, loc);
3749 Statement* s = Statement::make_goto_unnamed_statement(dest, loc);
3750 then_block->add_statement(s);
3751 s = Statement::make_if_statement(cond, then_block, NULL, loc);
3752 b->add_statement(s);
3755 if (this->statements_ != NULL
3756 || (!this->is_fallthrough_
3757 && stmts_label != NULL
3758 && *stmts_label != NULL))
3760 gcc_assert(!this->is_fallthrough_);
3761 if (stmts_label != NULL && *stmts_label != NULL)
3763 gcc_assert(!this->is_default_);
3764 if (this->statements_ != NULL)
3765 (*stmts_label)->set_location(this->statements_->start_location());
3766 Statement* s = Statement::make_unnamed_label_statement(*stmts_label);
3767 b->add_statement(s);
3768 *stmts_label = NULL;
3770 if (this->statements_ != NULL)
3771 b->add_statement(Statement::make_block_statement(this->statements_,
3775 if (this->is_fallthrough_)
3776 gcc_assert(next_case_label == NULL);
3779 source_location gloc = (this->statements_ == NULL
3781 : this->statements_->end_location());
3782 b->add_statement(Statement::make_goto_unnamed_statement(break_label,
3784 if (next_case_label != NULL)
3787 Statement::make_unnamed_label_statement(next_case_label);
3788 b->add_statement(s);
3793 // Class Type_case_clauses.
3798 Type_case_clauses::traverse(Traverse* traverse)
3800 for (Type_clauses::iterator p = this->clauses_.begin();
3801 p != this->clauses_.end();
3804 if (p->traverse(traverse) == TRAVERSE_EXIT)
3805 return TRAVERSE_EXIT;
3807 return TRAVERSE_CONTINUE;
3810 // Check for duplicate types.
3813 Type_case_clauses::check_duplicates() const
3815 typedef Unordered_set_hash(const Type*, Type_hash_identical,
3816 Type_identical) Types_seen;
3817 Types_seen types_seen;
3818 for (Type_clauses::const_iterator p = this->clauses_.begin();
3819 p != this->clauses_.end();
3822 Type* t = p->type();
3825 if (t->is_nil_constant_as_type())
3826 t = Type::make_nil_type();
3827 std::pair<Types_seen::iterator, bool> ins = types_seen.insert(t);
3829 error_at(p->location(), "duplicate type in switch");
3833 // Lower the clauses in a type switch. Add statements to the block B.
3834 // The type descriptor we are switching on is in DESCRIPTOR_TEMP.
3835 // BREAK_LABEL is the label at the end of the type switch.
3838 Type_case_clauses::lower(Block* b, Temporary_statement* descriptor_temp,
3839 Unnamed_label* break_label) const
3841 const Type_case_clause* default_case = NULL;
3843 Unnamed_label* stmts_label = NULL;
3844 for (Type_clauses::const_iterator p = this->clauses_.begin();
3845 p != this->clauses_.end();
3848 if (!p->is_default())
3849 p->lower(b, descriptor_temp, break_label, &stmts_label);
3852 // We are generating a series of tests, which means that we
3853 // need to move the default case to the end.
3857 gcc_assert(stmts_label == NULL);
3859 if (default_case != NULL)
3860 default_case->lower(b, descriptor_temp, break_label, NULL);
3863 // Class Type_switch_statement.
3868 Type_switch_statement::do_traverse(Traverse* traverse)
3870 if (this->var_ == NULL)
3872 if (this->traverse_expression(traverse, &this->expr_) == TRAVERSE_EXIT)
3873 return TRAVERSE_EXIT;
3875 if (this->clauses_ != NULL)
3876 return this->clauses_->traverse(traverse);
3877 return TRAVERSE_CONTINUE;
3880 // Lower a type switch statement to a series of if statements. The gc
3881 // compiler is able to generate a table in some cases. However, that
3882 // does not work for us because we may have type descriptors in
3883 // different shared libraries, so we can't compare them with simple
3884 // equality testing.
3887 Type_switch_statement::do_lower(Gogo*, Block* enclosing)
3889 const source_location loc = this->location();
3891 if (this->clauses_ != NULL)
3892 this->clauses_->check_duplicates();
3894 Block* b = new Block(enclosing, loc);
3896 Type* val_type = (this->var_ != NULL
3897 ? this->var_->var_value()->type()
3898 : this->expr_->type());
3900 // var descriptor_temp DESCRIPTOR_TYPE
3901 Type* descriptor_type = Type::make_type_descriptor_ptr_type();
3902 Temporary_statement* descriptor_temp =
3903 Statement::make_temporary(descriptor_type, NULL, loc);
3904 b->add_statement(descriptor_temp);
3906 if (val_type->interface_type() == NULL)
3908 // Doing a type switch on a non-interface type. Should we issue
3909 // a warning for this case?
3910 Expression* lhs = Expression::make_temporary_reference(descriptor_temp,
3913 if (val_type->is_nil_type())
3914 rhs = Expression::make_nil(loc);
3917 if (val_type->is_abstract())
3918 val_type = val_type->make_non_abstract_type();
3919 rhs = Expression::make_type_descriptor(val_type, loc);
3921 Statement* s = Statement::make_assignment(lhs, rhs, loc);
3922 b->add_statement(s);
3926 const source_location bloc = BUILTINS_LOCATION;
3928 // func {efacetype,ifacetype}(*interface) *descriptor
3929 // FIXME: This should be inlined.
3930 Typed_identifier_list* param_types = new Typed_identifier_list();
3931 param_types->push_back(Typed_identifier("i", val_type, bloc));
3932 Typed_identifier_list* ret_types = new Typed_identifier_list();
3933 ret_types->push_back(Typed_identifier("", descriptor_type, bloc));
3934 Function_type* fntype = Type::make_function_type(NULL, param_types,
3936 bool is_empty = val_type->interface_type()->is_empty();
3937 const char* fnname = is_empty ? "efacetype" : "ifacetype";
3939 Named_object::make_function_declaration(fnname, NULL, fntype, bloc);
3940 const char* asm_name = (is_empty
3941 ? "runtime.efacetype"
3942 : "runtime.ifacetype");
3943 fn->func_declaration_value()->set_asm_name(asm_name);
3945 // descriptor_temp = ifacetype(val_temp)
3946 Expression* func = Expression::make_func_reference(fn, NULL, loc);
3947 Expression_list* params = new Expression_list();
3949 if (this->var_ == NULL)
3952 ref = Expression::make_var_reference(this->var_, loc);
3953 params->push_back(ref);
3954 Expression* call = Expression::make_call(func, params, false, loc);
3955 Expression* lhs = Expression::make_temporary_reference(descriptor_temp,
3957 Statement* s = Statement::make_assignment(lhs, call, loc);
3958 b->add_statement(s);
3961 if (this->clauses_ != NULL)
3962 this->clauses_->lower(b, descriptor_temp, this->break_label());
3964 Statement* s = Statement::make_unnamed_label_statement(this->break_label_);
3965 b->add_statement(s);
3967 return Statement::make_block_statement(b, loc);
3970 // Return the break label for this type switch statement, creating it
3974 Type_switch_statement::break_label()
3976 if (this->break_label_ == NULL)
3977 this->break_label_ = new Unnamed_label(this->location());
3978 return this->break_label_;
3981 // Make a type switch statement.
3983 Type_switch_statement*
3984 Statement::make_type_switch_statement(Named_object* var, Expression* expr,
3985 source_location location)
3987 return new Type_switch_statement(var, expr, location);
3990 // Class Send_statement.
3995 Send_statement::do_traverse(Traverse* traverse)
3997 if (this->traverse_expression(traverse, &this->channel_) == TRAVERSE_EXIT)
3998 return TRAVERSE_EXIT;
3999 return this->traverse_expression(traverse, &this->val_);
4005 Send_statement::do_determine_types()
4007 this->channel_->determine_type_no_context();
4008 Type* type = this->channel_->type();
4009 Type_context context;
4010 if (type->channel_type() != NULL)
4011 context.type = type->channel_type()->element_type();
4012 this->val_->determine_type(&context);
4018 Send_statement::do_check_types(Gogo*)
4020 Type* type = this->channel_->type();
4021 if (type->is_error_type())
4023 this->set_is_error();
4026 Channel_type* channel_type = type->channel_type();
4027 if (channel_type == NULL)
4029 error_at(this->location(), "left operand of %<<-%> must be channel");
4030 this->set_is_error();
4033 Type* element_type = channel_type->element_type();
4034 if (!Type::are_assignable(element_type, this->val_->type(), NULL))
4036 this->report_error(_("incompatible types in send"));
4039 if (!channel_type->may_send())
4041 this->report_error(_("invalid send on receive-only channel"));
4046 // Get a tree for a send statement.
4049 Send_statement::do_get_tree(Translate_context* context)
4051 tree channel = this->channel_->get_tree(context);
4052 tree val = this->val_->get_tree(context);
4053 if (channel == error_mark_node || val == error_mark_node)
4054 return error_mark_node;
4055 Channel_type* channel_type = this->channel_->type()->channel_type();
4056 val = Expression::convert_for_assignment(context,
4057 channel_type->element_type(),
4061 return Gogo::send_on_channel(channel, val, true, this->for_select_,
4065 // Make a send statement.
4068 Statement::make_send_statement(Expression* channel, Expression* val,
4069 source_location location)
4071 return new Send_statement(channel, val, location);
4074 // Class Select_clauses::Select_clause.
4079 Select_clauses::Select_clause::traverse(Traverse* traverse)
4081 if (!this->is_lowered_
4082 && (traverse->traverse_mask()
4083 & (Traverse::traverse_types | Traverse::traverse_expressions)) != 0)
4085 if (this->channel_ != NULL)
4087 if (Expression::traverse(&this->channel_, traverse) == TRAVERSE_EXIT)
4088 return TRAVERSE_EXIT;
4090 if (this->val_ != NULL)
4092 if (Expression::traverse(&this->val_, traverse) == TRAVERSE_EXIT)
4093 return TRAVERSE_EXIT;
4096 if (this->statements_ != NULL)
4098 if (this->statements_->traverse(traverse) == TRAVERSE_EXIT)
4099 return TRAVERSE_EXIT;
4101 return TRAVERSE_CONTINUE;
4104 // Lowering. Here we pull out the channel and the send values, to
4105 // enforce the order of evaluation. We also add explicit send and
4106 // receive statements to the clauses.
4109 Select_clauses::Select_clause::lower(Block* b)
4111 if (this->is_default_)
4113 gcc_assert(this->channel_ == NULL && this->val_ == NULL);
4114 this->is_lowered_ = true;
4118 source_location loc = this->location_;
4120 // Evaluate the channel before the select statement.
4121 Temporary_statement* channel_temp = Statement::make_temporary(NULL,
4124 b->add_statement(channel_temp);
4125 this->channel_ = Expression::make_temporary_reference(channel_temp, loc);
4127 // If this is a send clause, evaluate the value to send before the
4128 // select statement.
4129 Temporary_statement* val_temp = NULL;
4130 if (this->is_send_ && !this->val_->is_constant())
4132 val_temp = Statement::make_temporary(NULL, this->val_, loc);
4133 b->add_statement(val_temp);
4136 // Add the send or receive before the rest of the statements if any.
4137 Block *init = new Block(b, loc);
4138 Expression* ref = Expression::make_temporary_reference(channel_temp, loc);
4142 if (val_temp == NULL)
4145 ref2 = Expression::make_temporary_reference(val_temp, loc);
4146 Send_statement* send = Statement::make_send_statement(ref, ref2, loc);
4147 send->set_for_select();
4148 init->add_statement(send);
4152 Receive_expression* recv = Expression::make_receive(ref, loc);
4153 recv->set_for_select();
4154 if (this->val_ != NULL)
4156 gcc_assert(this->var_ == NULL);
4157 init->add_statement(Statement::make_assignment(this->val_, recv,
4160 else if (this->var_ != NULL)
4162 this->var_->var_value()->set_init(recv);
4163 this->var_->var_value()->clear_type_from_chan_element();
4167 recv->discarding_value();
4168 init->add_statement(Statement::make_statement(recv));
4172 if (this->statements_ != NULL)
4173 init->add_statement(Statement::make_block_statement(this->statements_,
4176 this->statements_ = init;
4178 // Now all references should be handled through the statements, not
4180 this->is_lowered_ = true;
4188 Select_clauses::Select_clause::determine_types()
4190 gcc_assert(this->is_lowered_);
4191 if (this->statements_ != NULL)
4192 this->statements_->determine_types();
4195 // Whether this clause may fall through to the statement which follows
4196 // the overall select statement.
4199 Select_clauses::Select_clause::may_fall_through() const
4201 if (this->statements_ == NULL)
4203 return this->statements_->may_fall_through();
4206 // Return a tree for the statements to execute.
4209 Select_clauses::Select_clause::get_statements_tree(Translate_context* context)
4211 if (this->statements_ == NULL)
4213 return this->statements_->get_tree(context);
4216 // Class Select_clauses.
4221 Select_clauses::traverse(Traverse* traverse)
4223 for (Clauses::iterator p = this->clauses_.begin();
4224 p != this->clauses_.end();
4227 if (p->traverse(traverse) == TRAVERSE_EXIT)
4228 return TRAVERSE_EXIT;
4230 return TRAVERSE_CONTINUE;
4233 // Lowering. Here we pull out the channel and the send values, to
4234 // enforce the order of evaluation. We also add explicit send and
4235 // receive statements to the clauses.
4238 Select_clauses::lower(Block* b)
4240 for (Clauses::iterator p = this->clauses_.begin();
4241 p != this->clauses_.end();
4249 Select_clauses::determine_types()
4251 for (Clauses::iterator p = this->clauses_.begin();
4252 p != this->clauses_.end();
4254 p->determine_types();
4257 // Return whether these select clauses fall through to the statement
4258 // following the overall select statement.
4261 Select_clauses::may_fall_through() const
4263 for (Clauses::const_iterator p = this->clauses_.begin();
4264 p != this->clauses_.end();
4266 if (p->may_fall_through())
4271 // Return a tree. We build a call to
4272 // size_t __go_select(size_t count, _Bool has_default,
4273 // channel* channels, _Bool* is_send)
4275 // There are COUNT entries in the CHANNELS and IS_SEND arrays. The
4276 // value in the IS_SEND array is true for send, false for receive.
4277 // __go_select returns an integer from 0 to COUNT, inclusive. A
4278 // return of 0 means that the default case should be run; this only
4279 // happens if HAS_DEFAULT is non-zero. Otherwise the number indicates
4282 // FIXME: This doesn't handle channels which send interface types
4283 // where the receiver has a static type which matches that interface.
4286 Select_clauses::get_tree(Translate_context* context,
4287 Unnamed_label *break_label,
4288 source_location location)
4290 size_t count = this->clauses_.size();
4291 VEC(constructor_elt, gc)* chan_init = VEC_alloc(constructor_elt, gc, count);
4292 VEC(constructor_elt, gc)* is_send_init = VEC_alloc(constructor_elt, gc,
4294 Select_clause* default_clause = NULL;
4295 tree final_stmt_list = NULL_TREE;
4296 tree channel_type_tree = NULL_TREE;
4299 for (Clauses::iterator p = this->clauses_.begin();
4300 p != this->clauses_.end();
4303 if (p->is_default())
4305 default_clause = &*p;
4310 if (p->channel()->type()->channel_type() == NULL)
4312 // We should have given an error in the send or receive
4313 // statement we created via lowering.
4314 gcc_assert(saw_errors());
4315 return error_mark_node;
4318 tree channel_tree = p->channel()->get_tree(context);
4319 if (channel_tree == error_mark_node)
4320 return error_mark_node;
4321 channel_type_tree = TREE_TYPE(channel_tree);
4323 constructor_elt* elt = VEC_quick_push(constructor_elt, chan_init, NULL);
4324 elt->index = build_int_cstu(sizetype, i);
4325 elt->value = channel_tree;
4327 elt = VEC_quick_push(constructor_elt, is_send_init, NULL);
4328 elt->index = build_int_cstu(sizetype, i);
4329 elt->value = p->is_send() ? boolean_true_node : boolean_false_node;
4333 gcc_assert(i == count);
4335 if (i == 0 && default_clause != NULL)
4337 // There is only a default clause.
4338 gcc_assert(final_stmt_list == NULL_TREE);
4339 tree stmt_list = NULL_TREE;
4340 append_to_statement_list(default_clause->get_statements_tree(context),
4342 append_to_statement_list(break_label->get_definition(), &stmt_list);
4346 tree pointer_chan_type_tree = (channel_type_tree == NULL_TREE
4348 : build_pointer_type(channel_type_tree));
4350 tree pointer_boolean_type_tree = build_pointer_type(boolean_type_node);
4355 chans_arg = fold_convert_loc(location, pointer_chan_type_tree,
4357 is_sends_arg = fold_convert_loc(location, pointer_boolean_type_tree,
4362 tree index_type_tree = build_index_type(size_int(count - 1));
4363 tree chan_array_type_tree = build_array_type(channel_type_tree,
4365 tree chan_constructor = build_constructor(chan_array_type_tree,
4367 tree chan_var = create_tmp_var(chan_array_type_tree, "CHAN");
4368 DECL_IGNORED_P(chan_var) = 0;
4369 DECL_INITIAL(chan_var) = chan_constructor;
4370 DECL_SOURCE_LOCATION(chan_var) = location;
4371 TREE_ADDRESSABLE(chan_var) = 1;
4372 tree decl_expr = build1(DECL_EXPR, void_type_node, chan_var);
4373 SET_EXPR_LOCATION(decl_expr, location);
4374 append_to_statement_list(decl_expr, &final_stmt_list);
4376 tree is_send_array_type_tree = build_array_type(boolean_type_node,
4378 tree is_send_constructor = build_constructor(is_send_array_type_tree,
4380 tree is_send_var = create_tmp_var(is_send_array_type_tree, "ISSEND");
4381 DECL_IGNORED_P(is_send_var) = 0;
4382 DECL_INITIAL(is_send_var) = is_send_constructor;
4383 DECL_SOURCE_LOCATION(is_send_var) = location;
4384 TREE_ADDRESSABLE(is_send_var) = 1;
4385 decl_expr = build1(DECL_EXPR, void_type_node, is_send_var);
4386 SET_EXPR_LOCATION(decl_expr, location);
4387 append_to_statement_list(decl_expr, &final_stmt_list);
4389 chans_arg = fold_convert_loc(location, pointer_chan_type_tree,
4390 build_fold_addr_expr_loc(location,
4392 is_sends_arg = fold_convert_loc(location, pointer_boolean_type_tree,
4393 build_fold_addr_expr_loc(location,
4397 static tree select_fndecl;
4398 tree call = Gogo::call_builtin(&select_fndecl,
4406 (default_clause == NULL
4407 ? boolean_false_node
4408 : boolean_true_node),
4409 pointer_chan_type_tree,
4411 pointer_boolean_type_tree,
4413 if (call == error_mark_node)
4414 return error_mark_node;
4416 tree stmt_list = NULL_TREE;
4418 if (default_clause != NULL)
4419 this->add_clause_tree(context, 0, default_clause, break_label, &stmt_list);
4422 for (Clauses::iterator p = this->clauses_.begin();
4423 p != this->clauses_.end();
4426 if (!p->is_default())
4428 this->add_clause_tree(context, i, &*p, break_label, &stmt_list);
4433 append_to_statement_list(break_label->get_definition(), &stmt_list);
4435 tree switch_stmt = build3(SWITCH_EXPR, sizetype, call, stmt_list, NULL_TREE);
4436 SET_EXPR_LOCATION(switch_stmt, location);
4437 append_to_statement_list(switch_stmt, &final_stmt_list);
4439 return final_stmt_list;
4442 // Add the tree for CLAUSE to STMT_LIST.
4445 Select_clauses::add_clause_tree(Translate_context* context, int case_index,
4446 Select_clause* clause,
4447 Unnamed_label* bottom_label, tree* stmt_list)
4449 tree label = create_artificial_label(clause->location());
4450 append_to_statement_list(build3(CASE_LABEL_EXPR, void_type_node,
4451 build_int_cst(sizetype, case_index),
4454 append_to_statement_list(clause->get_statements_tree(context), stmt_list);
4455 tree g = bottom_label->get_goto(clause->statements() == NULL
4456 ? clause->location()
4457 : clause->statements()->end_location());
4458 append_to_statement_list(g, stmt_list);
4461 // Class Select_statement.
4463 // Return the break label for this switch statement, creating it if
4467 Select_statement::break_label()
4469 if (this->break_label_ == NULL)
4470 this->break_label_ = new Unnamed_label(this->location());
4471 return this->break_label_;
4474 // Lower a select statement. This will still return a select
4475 // statement, but it will be modified to implement the order of
4476 // evaluation rules, and to include the send and receive statements as
4477 // explicit statements in the clauses.
4480 Select_statement::do_lower(Gogo*, Block* enclosing)
4482 if (this->is_lowered_)
4484 Block* b = new Block(enclosing, this->location());
4485 this->clauses_->lower(b);
4486 this->is_lowered_ = true;
4487 b->add_statement(this);
4488 return Statement::make_block_statement(b, this->location());
4491 // Return the tree for a select statement.
4494 Select_statement::do_get_tree(Translate_context* context)
4496 return this->clauses_->get_tree(context, this->break_label(),
4500 // Make a select statement.
4503 Statement::make_select_statement(source_location location)
4505 return new Select_statement(location);
4508 // Class For_statement.
4513 For_statement::do_traverse(Traverse* traverse)
4515 if (this->init_ != NULL)
4517 if (this->init_->traverse(traverse) == TRAVERSE_EXIT)
4518 return TRAVERSE_EXIT;
4520 if (this->cond_ != NULL)
4522 if (this->traverse_expression(traverse, &this->cond_) == TRAVERSE_EXIT)
4523 return TRAVERSE_EXIT;
4525 if (this->post_ != NULL)
4527 if (this->post_->traverse(traverse) == TRAVERSE_EXIT)
4528 return TRAVERSE_EXIT;
4530 return this->statements_->traverse(traverse);
4533 // Lower a For_statement into if statements and gotos. Getting rid of
4534 // complex statements make it easier to handle garbage collection.
4537 For_statement::do_lower(Gogo*, Block* enclosing)
4540 source_location loc = this->location();
4542 Block* b = new Block(enclosing, this->location());
4543 if (this->init_ != NULL)
4545 s = Statement::make_block_statement(this->init_,
4546 this->init_->start_location());
4547 b->add_statement(s);
4550 Unnamed_label* entry = NULL;
4551 if (this->cond_ != NULL)
4553 entry = new Unnamed_label(this->location());
4554 b->add_statement(Statement::make_goto_unnamed_statement(entry, loc));
4557 Unnamed_label* top = new Unnamed_label(this->location());
4558 b->add_statement(Statement::make_unnamed_label_statement(top));
4560 s = Statement::make_block_statement(this->statements_,
4561 this->statements_->start_location());
4562 b->add_statement(s);
4564 source_location end_loc = this->statements_->end_location();
4566 Unnamed_label* cont = this->continue_label_;
4568 b->add_statement(Statement::make_unnamed_label_statement(cont));
4570 if (this->post_ != NULL)
4572 s = Statement::make_block_statement(this->post_,
4573 this->post_->start_location());
4574 b->add_statement(s);
4575 end_loc = this->post_->end_location();
4578 if (this->cond_ == NULL)
4579 b->add_statement(Statement::make_goto_unnamed_statement(top, end_loc));
4582 b->add_statement(Statement::make_unnamed_label_statement(entry));
4584 source_location cond_loc = this->cond_->location();
4585 Block* then_block = new Block(b, cond_loc);
4586 s = Statement::make_goto_unnamed_statement(top, cond_loc);
4587 then_block->add_statement(s);
4589 s = Statement::make_if_statement(this->cond_, then_block, NULL, cond_loc);
4590 b->add_statement(s);
4593 Unnamed_label* brk = this->break_label_;
4595 b->add_statement(Statement::make_unnamed_label_statement(brk));
4597 b->set_end_location(end_loc);
4599 return Statement::make_block_statement(b, loc);
4602 // Return the break label, creating it if necessary.
4605 For_statement::break_label()
4607 if (this->break_label_ == NULL)
4608 this->break_label_ = new Unnamed_label(this->location());
4609 return this->break_label_;
4612 // Return the continue LABEL_EXPR.
4615 For_statement::continue_label()
4617 if (this->continue_label_ == NULL)
4618 this->continue_label_ = new Unnamed_label(this->location());
4619 return this->continue_label_;
4622 // Set the break and continue labels a for statement. This is used
4623 // when lowering a for range statement.
4626 For_statement::set_break_continue_labels(Unnamed_label* break_label,
4627 Unnamed_label* continue_label)
4629 gcc_assert(this->break_label_ == NULL && this->continue_label_ == NULL);
4630 this->break_label_ = break_label;
4631 this->continue_label_ = continue_label;
4634 // Make a for statement.
4637 Statement::make_for_statement(Block* init, Expression* cond, Block* post,
4638 source_location location)
4640 return new For_statement(init, cond, post, location);
4643 // Class For_range_statement.
4648 For_range_statement::do_traverse(Traverse* traverse)
4650 if (this->traverse_expression(traverse, &this->index_var_) == TRAVERSE_EXIT)
4651 return TRAVERSE_EXIT;
4652 if (this->value_var_ != NULL)
4654 if (this->traverse_expression(traverse, &this->value_var_)
4656 return TRAVERSE_EXIT;
4658 if (this->traverse_expression(traverse, &this->range_) == TRAVERSE_EXIT)
4659 return TRAVERSE_EXIT;
4660 return this->statements_->traverse(traverse);
4663 // Lower a for range statement. For simplicity we lower this into a
4664 // for statement, which will then be lowered in turn to goto
4668 For_range_statement::do_lower(Gogo* gogo, Block* enclosing)
4670 Type* range_type = this->range_->type();
4671 if (range_type->points_to() != NULL
4672 && range_type->points_to()->array_type() != NULL
4673 && !range_type->points_to()->is_open_array_type())
4674 range_type = range_type->points_to();
4677 Type* value_type = NULL;
4678 if (range_type->array_type() != NULL)
4680 index_type = Type::lookup_integer_type("int");
4681 value_type = range_type->array_type()->element_type();
4683 else if (range_type->is_string_type())
4685 index_type = Type::lookup_integer_type("int");
4686 value_type = index_type;
4688 else if (range_type->map_type() != NULL)
4690 index_type = range_type->map_type()->key_type();
4691 value_type = range_type->map_type()->val_type();
4693 else if (range_type->channel_type() != NULL)
4695 index_type = range_type->channel_type()->element_type();
4696 if (this->value_var_ != NULL)
4698 if (!this->value_var_->type()->is_error_type())
4699 this->report_error(_("too many variables for range clause "
4701 return Statement::make_error_statement(this->location());
4706 this->report_error(_("range clause must have "
4707 "array, slice, setring, map, or channel type"));
4708 return Statement::make_error_statement(this->location());
4711 source_location loc = this->location();
4712 Block* temp_block = new Block(enclosing, loc);
4714 Named_object* range_object = NULL;
4715 Temporary_statement* range_temp = NULL;
4716 Var_expression* ve = this->range_->var_expression();
4718 range_object = ve->named_object();
4721 range_temp = Statement::make_temporary(NULL, this->range_, loc);
4722 temp_block->add_statement(range_temp);
4725 Temporary_statement* index_temp = Statement::make_temporary(index_type,
4727 temp_block->add_statement(index_temp);
4729 Temporary_statement* value_temp = NULL;
4730 if (this->value_var_ != NULL)
4732 value_temp = Statement::make_temporary(value_type, NULL, loc);
4733 temp_block->add_statement(value_temp);
4736 Block* body = new Block(temp_block, loc);
4743 // Arrange to do a loop appropriate for the type. We will produce
4744 // for INIT ; COND ; POST {
4746 // INDEX = INDEX_TEMP
4747 // VALUE = VALUE_TEMP // If there is a value
4748 // original statements
4751 if (range_type->array_type() != NULL)
4752 this->lower_range_array(gogo, temp_block, body, range_object, range_temp,
4753 index_temp, value_temp, &init, &cond, &iter_init,
4755 else if (range_type->is_string_type())
4756 this->lower_range_string(gogo, temp_block, body, range_object, range_temp,
4757 index_temp, value_temp, &init, &cond, &iter_init,
4759 else if (range_type->map_type() != NULL)
4760 this->lower_range_map(gogo, temp_block, body, range_object, range_temp,
4761 index_temp, value_temp, &init, &cond, &iter_init,
4763 else if (range_type->channel_type() != NULL)
4764 this->lower_range_channel(gogo, temp_block, body, range_object, range_temp,
4765 index_temp, value_temp, &init, &cond, &iter_init,
4770 if (iter_init != NULL)
4771 body->add_statement(Statement::make_block_statement(iter_init, loc));
4774 Expression* index_ref = Expression::make_temporary_reference(index_temp, loc);
4775 if (this->value_var_ == NULL)
4777 assign = Statement::make_assignment(this->index_var_, index_ref, loc);
4781 Expression_list* lhs = new Expression_list();
4782 lhs->push_back(this->index_var_);
4783 lhs->push_back(this->value_var_);
4785 Expression_list* rhs = new Expression_list();
4786 rhs->push_back(index_ref);
4787 rhs->push_back(Expression::make_temporary_reference(value_temp, loc));
4789 assign = Statement::make_tuple_assignment(lhs, rhs, loc);
4791 body->add_statement(assign);
4793 body->add_statement(Statement::make_block_statement(this->statements_, loc));
4795 body->set_end_location(this->statements_->end_location());
4797 For_statement* loop = Statement::make_for_statement(init, cond, post,
4799 loop->add_statements(body);
4800 loop->set_break_continue_labels(this->break_label_, this->continue_label_);
4802 temp_block->add_statement(loop);
4804 return Statement::make_block_statement(temp_block, loc);
4807 // Return a reference to the range, which may be in RANGE_OBJECT or in
4811 For_range_statement::make_range_ref(Named_object* range_object,
4812 Temporary_statement* range_temp,
4813 source_location loc)
4815 if (range_object != NULL)
4816 return Expression::make_var_reference(range_object, loc);
4818 return Expression::make_temporary_reference(range_temp, loc);
4821 // Return a call to the predeclared function FUNCNAME passing a
4822 // reference to the temporary variable ARG.
4825 For_range_statement::call_builtin(Gogo* gogo, const char* funcname,
4827 source_location loc)
4829 Named_object* no = gogo->lookup_global(funcname);
4830 gcc_assert(no != NULL && no->is_function_declaration());
4831 Expression* func = Expression::make_func_reference(no, NULL, loc);
4832 Expression_list* params = new Expression_list();
4833 params->push_back(arg);
4834 return Expression::make_call(func, params, false, loc);
4837 // Lower a for range over an array or slice.
4840 For_range_statement::lower_range_array(Gogo* gogo,
4843 Named_object* range_object,
4844 Temporary_statement* range_temp,
4845 Temporary_statement* index_temp,
4846 Temporary_statement* value_temp,
4852 source_location loc = this->location();
4854 // The loop we generate:
4855 // len_temp := len(range)
4856 // for index_temp = 0; index_temp < len_temp; index_temp++ {
4857 // value_temp = range[index_temp]
4858 // index = index_temp
4859 // value = value_temp
4865 // len_temp = len(range)
4868 Block* init = new Block(enclosing, loc);
4870 Expression* ref = this->make_range_ref(range_object, range_temp, loc);
4871 Expression* len_call = this->call_builtin(gogo, "len", ref, loc);
4872 Temporary_statement* len_temp = Statement::make_temporary(index_temp->type(),
4874 init->add_statement(len_temp);
4877 mpz_init_set_ui(zval, 0UL);
4878 Expression* zexpr = Expression::make_integer(&zval, NULL, loc);
4881 ref = Expression::make_temporary_reference(index_temp, loc);
4882 Statement* s = Statement::make_assignment(ref, zexpr, loc);
4883 init->add_statement(s);
4888 // index_temp < len_temp
4890 ref = Expression::make_temporary_reference(index_temp, loc);
4891 Expression* ref2 = Expression::make_temporary_reference(len_temp, loc);
4892 Expression* lt = Expression::make_binary(OPERATOR_LT, ref, ref2, loc);
4896 // Set *PITER_INIT to
4897 // value_temp = range[index_temp]
4899 Block* iter_init = NULL;
4900 if (value_temp != NULL)
4902 iter_init = new Block(body_block, loc);
4904 ref = this->make_range_ref(range_object, range_temp, loc);
4905 Expression* ref2 = Expression::make_temporary_reference(index_temp, loc);
4906 Expression* index = Expression::make_index(ref, ref2, NULL, loc);
4908 ref = Expression::make_temporary_reference(value_temp, loc);
4909 s = Statement::make_assignment(ref, index, loc);
4911 iter_init->add_statement(s);
4913 *piter_init = iter_init;
4918 Block* post = new Block(enclosing, loc);
4919 ref = Expression::make_temporary_reference(index_temp, loc);
4920 s = Statement::make_inc_statement(ref);
4921 post->add_statement(s);
4925 // Lower a for range over a string.
4928 For_range_statement::lower_range_string(Gogo* gogo,
4931 Named_object* range_object,
4932 Temporary_statement* range_temp,
4933 Temporary_statement* index_temp,
4934 Temporary_statement* value_temp,
4940 source_location loc = this->location();
4942 // The loop we generate:
4943 // var next_index_temp int
4944 // for index_temp = 0; ; index_temp = next_index_temp {
4945 // next_index_temp, value_temp = stringiter2(range, index_temp)
4946 // if next_index_temp == 0 {
4949 // index = index_temp
4950 // value = value_temp
4955 // var next_index_temp int
4958 Block* init = new Block(enclosing, loc);
4960 Temporary_statement* next_index_temp =
4961 Statement::make_temporary(index_temp->type(), NULL, loc);
4962 init->add_statement(next_index_temp);
4965 mpz_init_set_ui(zval, 0UL);
4966 Expression* zexpr = Expression::make_integer(&zval, NULL, loc);
4968 Expression* ref = Expression::make_temporary_reference(index_temp, loc);
4969 Statement* s = Statement::make_assignment(ref, zexpr, loc);
4971 init->add_statement(s);
4974 // The loop has no condition.
4978 // Set *PITER_INIT to
4979 // next_index_temp = runtime.stringiter(range, index_temp)
4981 // next_index_temp, value_temp = runtime.stringiter2(range, index_temp)
4983 // if next_index_temp == 0 {
4987 Block* iter_init = new Block(body_block, loc);
4990 if (value_temp == NULL)
4992 static Named_object* stringiter;
4993 if (stringiter == NULL)
4995 source_location bloc = BUILTINS_LOCATION;
4996 Type* int_type = gogo->lookup_global("int")->type_value();
4998 Typed_identifier_list* params = new Typed_identifier_list();
4999 params->push_back(Typed_identifier("s", Type::make_string_type(),
5001 params->push_back(Typed_identifier("k", int_type, bloc));
5003 Typed_identifier_list* results = new Typed_identifier_list();
5004 results->push_back(Typed_identifier("", int_type, bloc));
5006 Function_type* fntype = Type::make_function_type(NULL, params,
5008 stringiter = Named_object::make_function_declaration("stringiter",
5011 const char* n = "runtime.stringiter";
5012 stringiter->func_declaration_value()->set_asm_name(n);
5018 static Named_object* stringiter2;
5019 if (stringiter2 == NULL)
5021 source_location bloc = BUILTINS_LOCATION;
5022 Type* int_type = gogo->lookup_global("int")->type_value();
5024 Typed_identifier_list* params = new Typed_identifier_list();
5025 params->push_back(Typed_identifier("s", Type::make_string_type(),
5027 params->push_back(Typed_identifier("k", int_type, bloc));
5029 Typed_identifier_list* results = new Typed_identifier_list();
5030 results->push_back(Typed_identifier("", int_type, bloc));
5031 results->push_back(Typed_identifier("", int_type, bloc));
5033 Function_type* fntype = Type::make_function_type(NULL, params,
5035 stringiter2 = Named_object::make_function_declaration("stringiter",
5038 const char* n = "runtime.stringiter2";
5039 stringiter2->func_declaration_value()->set_asm_name(n);
5044 Expression* func = Expression::make_func_reference(no, NULL, loc);
5045 Expression_list* params = new Expression_list();
5046 params->push_back(this->make_range_ref(range_object, range_temp, loc));
5047 params->push_back(Expression::make_temporary_reference(index_temp, loc));
5048 Call_expression* call = Expression::make_call(func, params, false, loc);
5050 if (value_temp == NULL)
5052 ref = Expression::make_temporary_reference(next_index_temp, loc);
5053 s = Statement::make_assignment(ref, call, loc);
5057 Expression_list* lhs = new Expression_list();
5058 lhs->push_back(Expression::make_temporary_reference(next_index_temp,
5060 lhs->push_back(Expression::make_temporary_reference(value_temp, loc));
5062 Expression_list* rhs = new Expression_list();
5063 rhs->push_back(Expression::make_call_result(call, 0));
5064 rhs->push_back(Expression::make_call_result(call, 1));
5066 s = Statement::make_tuple_assignment(lhs, rhs, loc);
5068 iter_init->add_statement(s);
5070 ref = Expression::make_temporary_reference(next_index_temp, loc);
5071 zexpr = Expression::make_integer(&zval, NULL, loc);
5073 Expression* equals = Expression::make_binary(OPERATOR_EQEQ, ref, zexpr, loc);
5075 Block* then_block = new Block(iter_init, loc);
5076 s = Statement::make_break_statement(this->break_label(), loc);
5077 then_block->add_statement(s);
5079 s = Statement::make_if_statement(equals, then_block, NULL, loc);
5080 iter_init->add_statement(s);
5082 *piter_init = iter_init;
5085 // index_temp = next_index_temp
5087 Block* post = new Block(enclosing, loc);
5089 Expression* lhs = Expression::make_temporary_reference(index_temp, loc);
5090 Expression* rhs = Expression::make_temporary_reference(next_index_temp, loc);
5091 s = Statement::make_assignment(lhs, rhs, loc);
5093 post->add_statement(s);
5097 // Lower a for range over a map.
5100 For_range_statement::lower_range_map(Gogo* gogo,
5103 Named_object* range_object,
5104 Temporary_statement* range_temp,
5105 Temporary_statement* index_temp,
5106 Temporary_statement* value_temp,
5112 source_location loc = this->location();
5114 // The runtime uses a struct to handle ranges over a map. The
5115 // struct is four pointers long. The first pointer is NULL when we
5116 // have completed the iteration.
5118 // The loop we generate:
5119 // var hiter map_iteration_struct
5120 // for mapiterinit(range, &hiter); hiter[0] != nil; mapiternext(&hiter) {
5121 // mapiter2(hiter, &index_temp, &value_temp)
5122 // index = index_temp
5123 // value = value_temp
5128 // var hiter map_iteration_struct
5129 // runtime.mapiterinit(range, &hiter)
5131 Block* init = new Block(enclosing, loc);
5133 const unsigned long map_iteration_size = 4;
5136 mpz_init_set_ui(ival, map_iteration_size);
5137 Expression* iexpr = Expression::make_integer(&ival, NULL, loc);
5140 Type* byte_type = gogo->lookup_global("byte")->type_value();
5141 Type* ptr_type = Type::make_pointer_type(byte_type);
5143 Type* map_iteration_type = Type::make_array_type(ptr_type, iexpr);
5144 Type* map_iteration_ptr = Type::make_pointer_type(map_iteration_type);
5146 Temporary_statement* hiter = Statement::make_temporary(map_iteration_type,
5148 init->add_statement(hiter);
5150 source_location bloc = BUILTINS_LOCATION;
5151 Typed_identifier_list* param_types = new Typed_identifier_list();
5152 param_types->push_back(Typed_identifier("map", this->range_->type(), bloc));
5153 param_types->push_back(Typed_identifier("it", map_iteration_ptr, bloc));
5154 Function_type* fntype = Type::make_function_type(NULL, param_types, NULL,
5157 Named_object* mapiterinit =
5158 Named_object::make_function_declaration("mapiterinit", NULL, fntype, bloc);
5159 const char* n = "runtime.mapiterinit";
5160 mapiterinit->func_declaration_value()->set_asm_name(n);
5162 Expression* func = Expression::make_func_reference(mapiterinit, NULL, loc);
5163 Expression_list* params = new Expression_list();
5164 params->push_back(this->make_range_ref(range_object, range_temp, loc));
5165 Expression* ref = Expression::make_temporary_reference(hiter, loc);
5166 params->push_back(Expression::make_unary(OPERATOR_AND, ref, loc));
5167 Expression* call = Expression::make_call(func, params, false, loc);
5168 init->add_statement(Statement::make_statement(call));
5175 ref = Expression::make_temporary_reference(hiter, loc);
5178 mpz_init_set_ui(zval, 0UL);
5179 Expression* zexpr = Expression::make_integer(&zval, NULL, loc);
5182 Expression* index = Expression::make_index(ref, zexpr, NULL, loc);
5184 Expression* ne = Expression::make_binary(OPERATOR_NOTEQ, index,
5185 Expression::make_nil(loc),
5190 // Set *PITER_INIT to
5191 // mapiter1(hiter, &index_temp)
5193 // mapiter2(hiter, &index_temp, &value_temp)
5195 Block* iter_init = new Block(body_block, loc);
5197 param_types = new Typed_identifier_list();
5198 param_types->push_back(Typed_identifier("hiter", map_iteration_ptr, bloc));
5199 Type* pkey_type = Type::make_pointer_type(index_temp->type());
5200 param_types->push_back(Typed_identifier("key", pkey_type, bloc));
5201 if (value_temp != NULL)
5203 Type* pval_type = Type::make_pointer_type(value_temp->type());
5204 param_types->push_back(Typed_identifier("val", pval_type, bloc));
5206 fntype = Type::make_function_type(NULL, param_types, NULL, bloc);
5207 n = value_temp == NULL ? "mapiter1" : "mapiter2";
5208 Named_object* mapiter = Named_object::make_function_declaration(n, NULL,
5210 n = value_temp == NULL ? "runtime.mapiter1" : "runtime.mapiter2";
5211 mapiter->func_declaration_value()->set_asm_name(n);
5213 func = Expression::make_func_reference(mapiter, NULL, loc);
5214 params = new Expression_list();
5215 ref = Expression::make_temporary_reference(hiter, loc);
5216 params->push_back(Expression::make_unary(OPERATOR_AND, ref, loc));
5217 ref = Expression::make_temporary_reference(index_temp, loc);
5218 params->push_back(Expression::make_unary(OPERATOR_AND, ref, loc));
5219 if (value_temp != NULL)
5221 ref = Expression::make_temporary_reference(value_temp, loc);
5222 params->push_back(Expression::make_unary(OPERATOR_AND, ref, loc));
5224 call = Expression::make_call(func, params, false, loc);
5225 iter_init->add_statement(Statement::make_statement(call));
5227 *piter_init = iter_init;
5230 // mapiternext(&hiter)
5232 Block* post = new Block(enclosing, loc);
5234 static Named_object* mapiternext;
5235 if (mapiternext == NULL)
5237 param_types = new Typed_identifier_list();
5238 param_types->push_back(Typed_identifier("it", map_iteration_ptr, bloc));
5239 fntype = Type::make_function_type(NULL, param_types, NULL, bloc);
5240 mapiternext = Named_object::make_function_declaration("mapiternext",
5243 const char* n = "runtime.mapiternext";
5244 mapiternext->func_declaration_value()->set_asm_name(n);
5247 func = Expression::make_func_reference(mapiternext, NULL, loc);
5248 params = new Expression_list();
5249 ref = Expression::make_temporary_reference(hiter, loc);
5250 params->push_back(Expression::make_unary(OPERATOR_AND, ref, loc));
5251 call = Expression::make_call(func, params, false, loc);
5252 post->add_statement(Statement::make_statement(call));
5257 // Lower a for range over a channel.
5260 For_range_statement::lower_range_channel(Gogo* gogo,
5263 Named_object* range_object,
5264 Temporary_statement* range_temp,
5265 Temporary_statement* index_temp,
5266 Temporary_statement* value_temp,
5272 gcc_assert(value_temp == NULL);
5274 source_location loc = this->location();
5276 // The loop we generate:
5278 // index_temp = <-range
5279 // if closed(range) {
5282 // index = index_temp
5283 // value = value_temp
5287 // We have no initialization code, no condition, and no post code.
5293 // Set *PITER_INIT to
5294 // index_temp = <-range
5295 // if closed(range) {
5299 Block* iter_init = new Block(body_block, loc);
5301 Expression* ref = this->make_range_ref(range_object, range_temp, loc);
5302 Expression* cond = this->call_builtin(gogo, "closed", ref, loc);
5304 ref = this->make_range_ref(range_object, range_temp, loc);
5305 Expression* recv = Expression::make_receive(ref, loc);
5306 ref = Expression::make_temporary_reference(index_temp, loc);
5307 Statement* s = Statement::make_assignment(ref, recv, loc);
5308 iter_init->add_statement(s);
5310 Block* then_block = new Block(iter_init, loc);
5311 s = Statement::make_break_statement(this->break_label(), loc);
5312 then_block->add_statement(s);
5314 s = Statement::make_if_statement(cond, then_block, NULL, loc);
5315 iter_init->add_statement(s);
5317 *piter_init = iter_init;
5320 // Return the break LABEL_EXPR.
5323 For_range_statement::break_label()
5325 if (this->break_label_ == NULL)
5326 this->break_label_ = new Unnamed_label(this->location());
5327 return this->break_label_;
5330 // Return the continue LABEL_EXPR.
5333 For_range_statement::continue_label()
5335 if (this->continue_label_ == NULL)
5336 this->continue_label_ = new Unnamed_label(this->location());
5337 return this->continue_label_;
5340 // Make a for statement with a range clause.
5342 For_range_statement*
5343 Statement::make_for_range_statement(Expression* index_var,
5344 Expression* value_var,
5346 source_location location)
5348 return new For_range_statement(index_var, value_var, range, location);