PR libstdc++/87308 adjust regex used in std::any pretty printer
[official-gcc.git] / gcc / d / toir.cc
blob0d78fa60aa55b04be4e98e63d722696f77fe3118
1 /* toir.cc -- Lower D frontend statements to GCC trees.
2 Copyright (C) 2006-2018 Free Software Foundation, Inc.
4 GCC is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
9 GCC is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with GCC; see the file COPYING3. If not see
16 <http://www.gnu.org/licenses/>. */
18 #include "config.h"
19 #include "system.h"
20 #include "coretypes.h"
22 #include "dmd/aggregate.h"
23 #include "dmd/declaration.h"
24 #include "dmd/expression.h"
25 #include "dmd/identifier.h"
26 #include "dmd/init.h"
27 #include "dmd/statement.h"
29 #include "tree.h"
30 #include "tree-iterator.h"
31 #include "options.h"
32 #include "stmt.h"
33 #include "fold-const.h"
34 #include "diagnostic.h"
35 #include "stringpool.h"
36 #include "function.h"
37 #include "toplev.h"
39 #include "d-tree.h"
42 /* Update data for defined and undefined labels when leaving a scope. */
44 bool
45 pop_binding_label (Statement * const &, d_label_entry *ent, binding_level *bl)
47 binding_level *obl = bl->level_chain;
49 if (ent->level == bl)
51 if (bl->kind == level_try)
52 ent->in_try_scope = true;
53 else if (bl->kind == level_catch)
54 ent->in_catch_scope = true;
56 ent->level = obl;
58 else if (ent->fwdrefs)
60 for (d_label_use_entry *ref = ent->fwdrefs; ref; ref = ref->next)
61 ref->level = obl;
64 return true;
67 /* At the end of a function, all labels declared within the function
68 go out of scope. BLOCK is the top-level block for the function. */
70 bool
71 pop_label (Statement * const &s, d_label_entry *ent, tree block)
73 if (!ent->bc_label)
75 /* Put the labels into the "variables" of the top-level block,
76 so debugger can see them. */
77 if (DECL_NAME (ent->label))
79 gcc_assert (DECL_INITIAL (ent->label) != NULL_TREE);
80 DECL_CHAIN (ent->label) = BLOCK_VARS (block);
81 BLOCK_VARS (block) = ent->label;
85 d_function_chain->labels->remove (s);
87 return true;
90 /* The D front-end does not use the 'binding level' system for a symbol table,
91 however it has been the goto structure for tracking code flow.
92 Primarily it is only needed to get debugging information for local variables
93 and otherwise support the back-end. */
95 void
96 push_binding_level (level_kind kind)
98 /* Add it to the front of currently active scopes stack. */
99 binding_level *new_level = ggc_cleared_alloc<binding_level> ();
100 new_level->level_chain = current_binding_level;
101 new_level->kind = kind;
103 current_binding_level = new_level;
106 tree
107 pop_binding_level (void)
109 binding_level *level = current_binding_level;
110 current_binding_level = level->level_chain;
112 tree block = make_node (BLOCK);
113 BLOCK_VARS (block) = level->names;
114 BLOCK_SUBBLOCKS (block) = level->blocks;
116 /* In each subblock, record that this is its superior. */
117 for (tree t = level->blocks; t; t = BLOCK_CHAIN (t))
118 BLOCK_SUPERCONTEXT (t) = block;
120 if (level->kind == level_function)
122 /* Dispose of the block that we just made inside some higher level. */
123 DECL_INITIAL (current_function_decl) = block;
124 BLOCK_SUPERCONTEXT (block) = current_function_decl;
126 /* Pop all the labels declared in the function. */
127 if (d_function_chain->labels)
128 d_function_chain->labels->traverse<tree, &pop_label> (block);
130 else
132 /* Any uses of undefined labels, and any defined labels, now operate
133 under constraints of next binding contour. */
134 if (d_function_chain && d_function_chain->labels)
136 language_function *f = d_function_chain;
137 f->labels->traverse<binding_level *, &pop_binding_label> (level);
140 current_binding_level->blocks
141 = block_chainon (current_binding_level->blocks, block);
144 TREE_USED (block) = 1;
145 return block;
148 /* Create an empty statement tree rooted at T. */
150 void
151 push_stmt_list (void)
153 tree t = alloc_stmt_list ();
154 vec_safe_push (d_function_chain->stmt_list, t);
155 d_keep (t);
158 /* Finish the statement tree rooted at T. */
160 tree
161 pop_stmt_list (void)
163 tree t = d_function_chain->stmt_list->pop ();
165 /* If the statement list is completely empty, just return it. This is just
166 as good as build_empty_stmt, with the advantage that statement lists
167 are merged when they are appended to one another. So using the
168 STATEMENT_LIST avoids pathological buildup of EMPTY_STMT_P statements. */
169 if (TREE_SIDE_EFFECTS (t))
171 /* If the statement list contained exactly one statement, then extract
172 it immediately. */
173 tree_stmt_iterator i = tsi_start (t);
175 if (tsi_one_before_end_p (i))
177 tree u = tsi_stmt (i);
178 tsi_delink (&i);
179 free_stmt_list (t);
180 t = u;
184 return t;
187 /* T is an expression statement. Add it to the statement-tree. */
189 void
190 add_stmt (tree t)
192 /* Ignore (void) 0; expression statements received from the frontend.
193 Likewise void_node is used when contracts become nops in release code. */
194 if (t == void_node || IS_EMPTY_STMT (t))
195 return;
197 /* At this point, we no longer care about the value of expressions,
198 so if there's no side-effects, then don't add it. */
199 if (!TREE_SIDE_EFFECTS (t))
200 return;
202 if (TREE_CODE (t) == COMPOUND_EXPR)
204 /* Push out each comma expressions as separate statements. */
205 add_stmt (TREE_OPERAND (t, 0));
206 add_stmt (TREE_OPERAND (t, 1));
208 else
210 /* Force the type to be void so we don't need to create a temporary
211 variable to hold the inner expression. */
212 if (TREE_CODE (t) == CLEANUP_POINT_EXPR)
213 TREE_TYPE (t) = void_type_node;
215 /* Append the expression to the statement list.
216 Make sure it has a proper location. */
217 if (EXPR_P (t) && !EXPR_HAS_LOCATION (t))
218 SET_EXPR_LOCATION (t, input_location);
220 tree stmt_list = d_function_chain->stmt_list->last ();
221 append_to_statement_list_force (t, &stmt_list);
225 /* Implements the visitor interface to build the GCC trees of all Statement
226 AST classes emitted from the D Front-end.
227 All visit methods accept one parameter S, which holds the frontend AST
228 of the statement to compile. They also don't return any value, instead
229 generated code are pushed to add_stmt(), which appends them to the
230 statement list in the current_binding_level. */
232 class IRVisitor : public Visitor
234 using Visitor::visit;
236 FuncDeclaration *func_;
238 /* Stack of labels which are targets for "break" and "continue",
239 linked through TREE_CHAIN. */
240 tree break_label_;
241 tree continue_label_;
243 public:
244 IRVisitor (FuncDeclaration *fd)
246 this->func_ = fd;
247 this->break_label_ = NULL_TREE;
248 this->continue_label_ = NULL_TREE;
251 /* Helper for generating code for the statement AST class S.
252 Sets up the location of the statement before lowering. */
254 void build_stmt (Statement *s)
256 location_t saved_location = input_location;
257 input_location = make_location_t (s->loc);
258 s->accept (this);
259 input_location = saved_location;
262 /* Start a new scope for a KIND statement.
263 Each user-declared variable will have a binding contour that begins
264 where the variable is declared and ends at its containing scope. */
266 void start_scope (level_kind kind)
268 push_binding_level (kind);
269 push_stmt_list ();
272 /* Leave scope pushed by start_scope, returning a new bind_expr if
273 any variables where declared in the scope. */
275 tree end_scope (void)
277 tree block = pop_binding_level ();
278 tree body = pop_stmt_list ();
280 if (! BLOCK_VARS (block))
281 return body;
283 tree bind = build3 (BIND_EXPR, void_type_node,
284 BLOCK_VARS (block), body, block);
285 TREE_SIDE_EFFECTS (bind) = 1;
286 return bind;
289 /* Like end_scope, but also push it into the outer statement-tree. */
291 void finish_scope (void)
293 tree scope = this->end_scope ();
294 add_stmt (scope);
297 /* Return TRUE if IDENT is the current function return label. */
299 bool is_return_label (Identifier *ident)
301 if (this->func_->returnLabel)
302 return this->func_->returnLabel->ident == ident;
304 return false;
307 /* Define a label, specifying the location in the source file.
308 Return the LABEL_DECL node for the label. */
310 tree define_label (Statement *s, Identifier *ident = NULL)
312 tree label = this->lookup_label (s, ident);
313 gcc_assert (DECL_INITIAL (label) == NULL_TREE);
315 d_label_entry *ent = d_function_chain->labels->get (s);
316 gcc_assert (ent != NULL);
318 /* Mark label as having been defined. */
319 DECL_INITIAL (label) = error_mark_node;
321 ent->level = current_binding_level;
323 for (d_label_use_entry *ref = ent->fwdrefs; ref ; ref = ref->next)
324 this->check_previous_goto (ent->statement, ref);
325 ent->fwdrefs = NULL;
327 return label;
330 /* Emit a LABEL expression. */
332 void do_label (tree label)
334 /* Don't write out label unless it is marked as used by the frontend.
335 This makes auto-vectorization possible in conditional loops.
336 The only excemption to this is in the LabelStatement visitor,
337 in which all computed labels are marked regardless. */
338 if (TREE_USED (label))
339 add_stmt (build1 (LABEL_EXPR, void_type_node, label));
342 /* Emit a goto expression to LABEL. */
344 void do_jump (tree label)
346 add_stmt (fold_build1 (GOTO_EXPR, void_type_node, label));
347 TREE_USED (label) = 1;
350 /* Check that a new jump at statement scope FROM to a label declared in
351 statement scope TO is valid. */
353 void check_goto (Statement *from, Statement *to)
355 d_label_entry *ent = d_function_chain->labels->get (to);
356 gcc_assert (ent != NULL);
358 /* If the label hasn't been defined yet, defer checking. */
359 if (! DECL_INITIAL (ent->label))
361 d_label_use_entry *fwdref = ggc_alloc<d_label_use_entry> ();
362 fwdref->level = current_binding_level;
363 fwdref->statement = from;
364 fwdref->next = ent->fwdrefs;
365 ent->fwdrefs = fwdref;
366 return;
369 if (ent->in_try_scope)
370 error_at (make_location_t (from->loc), "cannot goto into try block");
371 else if (ent->in_catch_scope)
372 error_at (make_location_t (from->loc), "cannot goto into catch block");
375 /* Check that a previously seen jump to a newly defined label is valid.
376 S is the label statement; FWDREF is the jump context. This is called
377 for both user-defined and case labels. */
379 void check_previous_goto (Statement *s, d_label_use_entry *fwdref)
381 for (binding_level *b = current_binding_level; b ; b = b->level_chain)
383 if (b == fwdref->level)
384 break;
386 if (b->kind == level_try || b->kind == level_catch)
388 location_t location;
390 if (s->isLabelStatement ())
392 location = make_location_t (fwdref->statement->loc);
393 if (b->kind == level_try)
394 error_at (location, "cannot goto into try block");
395 else
396 error_at (location, "cannot goto into catch block");
398 else if (s->isCaseStatement ())
400 location = make_location_t (s->loc);
401 error_at (location, "case cannot be in different "
402 "try block level from switch");
404 else if (s->isDefaultStatement ())
406 location = make_location_t (s->loc);
407 error_at (location, "default cannot be in different "
408 "try block level from switch");
410 else
411 gcc_unreachable ();
416 /* Get or build LABEL_DECL using the IDENT and statement block S given. */
418 tree lookup_label (Statement *s, Identifier *ident = NULL)
420 /* You can't use labels at global scope. */
421 if (d_function_chain == NULL)
423 error ("label %s referenced outside of any function",
424 ident ? ident->toChars () : "(unnamed)");
425 return NULL_TREE;
428 /* Create the label htab for the function on demand. */
429 if (!d_function_chain->labels)
431 d_function_chain->labels
432 = hash_map<Statement *, d_label_entry>::create_ggc (13);
435 d_label_entry *ent = d_function_chain->labels->get (s);
436 if (ent != NULL)
437 return ent->label;
438 else
440 tree name = ident ? get_identifier (ident->toChars ()) : NULL_TREE;
441 tree decl = build_decl (make_location_t (s->loc), LABEL_DECL,
442 name, void_type_node);
443 DECL_CONTEXT (decl) = current_function_decl;
444 DECL_MODE (decl) = VOIDmode;
446 /* Create new empty slot. */
447 ent = ggc_cleared_alloc<d_label_entry> ();
448 ent->statement = s;
449 ent->label = decl;
451 bool existed = d_function_chain->labels->put (s, *ent);
452 gcc_assert (!existed);
454 return decl;
458 /* Get the LABEL_DECL to represent a break or continue for the
459 statement S given. BC indicates which. */
461 tree lookup_bc_label (Statement *s, bc_kind bc)
463 tree vec = this->lookup_label (s);
465 /* The break and continue labels are put into a TREE_VEC. */
466 if (TREE_CODE (vec) == LABEL_DECL)
468 d_label_entry *ent = d_function_chain->labels->get (s);
469 gcc_assert (ent != NULL);
471 vec = make_tree_vec (2);
472 TREE_VEC_ELT (vec, bc_break) = ent->label;
474 /* Build the continue label. */
475 tree label = build_decl (make_location_t (s->loc), LABEL_DECL,
476 NULL_TREE, void_type_node);
477 DECL_CONTEXT (label) = current_function_decl;
478 DECL_MODE (label) = VOIDmode;
479 TREE_VEC_ELT (vec, bc_continue) = label;
481 ent->label = vec;
482 ent->bc_label = true;
485 return TREE_VEC_ELT (vec, bc);
488 /* Set and return the current break label for the current block. */
490 tree push_break_label (Statement *s)
492 tree label = this->lookup_bc_label (s->getRelatedLabeled (), bc_break);
493 DECL_CHAIN (label) = this->break_label_;
494 this->break_label_ = label;
495 return label;
498 /* Finish with the current break label. */
500 void pop_break_label (tree label)
502 gcc_assert (this->break_label_ == label);
503 this->break_label_ = DECL_CHAIN (this->break_label_);
504 this->do_label (label);
507 /* Set and return the continue label for the current block. */
509 tree push_continue_label (Statement *s)
511 tree label = this->lookup_bc_label (s->getRelatedLabeled (), bc_continue);
512 DECL_CHAIN (label) = this->continue_label_;
513 this->continue_label_ = label;
514 return label;
517 /* Finish with the current continue label. */
519 void pop_continue_label (tree label)
521 gcc_assert (this->continue_label_ == label);
522 this->continue_label_ = DECL_CHAIN (this->continue_label_);
523 this->do_label (label);
526 /* Visitor interfaces. */
529 /* This should be overridden by each statement class. */
531 void visit (Statement *)
533 gcc_unreachable ();
536 /* The frontend lowers `scope (exit/failure/success)' statements as
537 try/catch/finally. At this point, this statement is just an empty
538 placeholder. Maybe the frontend shouldn't leak these. */
540 void visit (OnScopeStatement *)
544 /* If statements provide simple conditional execution of statements. */
546 void visit (IfStatement *s)
548 this->start_scope (level_cond);
550 /* Build the outer 'if' condition, which may produce temporaries
551 requiring scope destruction. */
552 tree ifcond = convert_for_condition (build_expr_dtor (s->condition),
553 s->condition->type);
554 tree ifbody = void_node;
555 tree elsebody = void_node;
557 /* Build the 'then' branch. */
558 if (s->ifbody)
560 push_stmt_list ();
561 this->build_stmt (s->ifbody);
562 ifbody = pop_stmt_list ();
565 /* Now build the 'else' branch, which may have nested 'else if' parts. */
566 if (s->elsebody)
568 push_stmt_list ();
569 this->build_stmt (s->elsebody);
570 elsebody = pop_stmt_list ();
573 /* Wrap up our constructed if condition into a COND_EXPR. */
574 tree cond = build_vcondition (ifcond, ifbody, elsebody);
575 add_stmt (cond);
577 /* Finish the if-then scope. */
578 this->finish_scope ();
581 /* Should there be any `pragma (...)' statements requiring code generation,
582 here would be the place to do it. For now, all pragmas are handled
583 by the frontend. */
585 void visit (PragmaStatement *)
589 /* The frontend lowers `while (...)' statements as `for (...)' loops.
590 This visitor is not strictly required other than to enforce that
591 these kinds of statements never reach here. */
593 void visit (WhileStatement *)
595 gcc_unreachable ();
598 /* Do while statments implement simple loops. The body is executed, then
599 the condition is evaluated. */
601 void visit (DoStatement *s)
603 tree lbreak = this->push_break_label (s);
605 this->start_scope (level_loop);
606 if (s->_body)
608 tree lcontinue = this->push_continue_label (s);
609 this->build_stmt (s->_body);
610 this->pop_continue_label (lcontinue);
613 /* Build the outer 'while' condition, which may produce temporaries
614 requiring scope destruction. */
615 tree exitcond = convert_for_condition (build_expr_dtor (s->condition),
616 s->condition->type);
617 add_stmt (build_vcondition (exitcond, void_node,
618 build1 (GOTO_EXPR, void_type_node, lbreak)));
619 TREE_USED (lbreak) = 1;
621 tree body = this->end_scope ();
622 add_stmt (build1 (LOOP_EXPR, void_type_node, body));
624 this->pop_break_label (lbreak);
627 /* For statements implement loops with initialization, test, and
628 increment clauses. */
630 void visit (ForStatement *s)
632 tree lbreak = this->push_break_label (s);
633 this->start_scope (level_loop);
635 if (s->_init)
636 this->build_stmt (s->_init);
638 if (s->condition)
640 tree exitcond = convert_for_condition (build_expr_dtor (s->condition),
641 s->condition->type);
642 add_stmt (build_vcondition (exitcond, void_node,
643 build1 (GOTO_EXPR, void_type_node,
644 lbreak)));
645 TREE_USED (lbreak) = 1;
648 if (s->_body)
650 tree lcontinue = this->push_continue_label (s);
651 this->build_stmt (s->_body);
652 this->pop_continue_label (lcontinue);
655 if (s->increment)
657 /* Force side effects? */
658 add_stmt (build_expr_dtor (s->increment));
661 tree body = this->end_scope ();
662 add_stmt (build1 (LOOP_EXPR, void_type_node, body));
664 this->pop_break_label (lbreak);
667 /* The frontend lowers `foreach (...)' statements as `for (...)' loops.
668 This visitor is not strictly required other than to enforce that
669 these kinds of statements never reach here. */
671 void visit (ForeachStatement *)
673 gcc_unreachable ();
676 /* The frontend lowers `foreach (...; [x..y])' statements as `for (...)'
677 loops. This visitor is not strictly required other than to enforce that
678 these kinds of statements never reach here. */
680 void visit (ForeachRangeStatement *)
682 gcc_unreachable ();
685 /* Jump to the associated exit label for the current loop. If IDENT
686 for the Statement is not null, then the label is user defined. */
688 void visit (BreakStatement *s)
690 if (s->ident)
692 /* The break label may actually be some levels up.
693 eg: on a try/finally wrapping a loop. */
694 LabelStatement *label = this->func_->searchLabel (s->ident)->statement;
695 gcc_assert (label != NULL);
696 Statement *stmt = label->statement->getRelatedLabeled ();
697 this->do_jump (this->lookup_bc_label (stmt, bc_break));
699 else
700 this->do_jump (this->break_label_);
703 /* Jump to the associated continue label for the current loop. If IDENT
704 for the Statement is not null, then the label is user defined. */
706 void visit (ContinueStatement *s)
708 if (s->ident)
710 LabelStatement *label = this->func_->searchLabel (s->ident)->statement;
711 gcc_assert (label != NULL);
712 this->do_jump (this->lookup_bc_label (label->statement,
713 bc_continue));
715 else
716 this->do_jump (this->continue_label_);
719 /* A goto statement jumps to the statement identified by the given label. */
721 void visit (GotoStatement *s)
723 gcc_assert (s->label->statement != NULL);
724 gcc_assert (s->tf == s->label->statement->tf);
726 /* If no label found, there was an error. */
727 tree label = this->lookup_label (s->label->statement, s->label->ident);
728 this->do_jump (label);
730 /* Need to error if the goto is jumping into a try or catch block. */
731 this->check_goto (s, s->label->statement);
734 /* Statements can be labeled. A label is an identifier that precedes
735 a statement. */
737 void visit (LabelStatement *s)
739 LabelDsymbol *sym;
741 if (this->is_return_label (s->ident))
742 sym = this->func_->returnLabel;
743 else
744 sym = this->func_->searchLabel (s->ident);
746 /* If no label found, there was an error. */
747 tree label = this->define_label (sym->statement, sym->ident);
748 TREE_USED (label) = 1;
750 this->do_label (label);
752 if (this->is_return_label (s->ident) && this->func_->fensure != NULL)
753 this->build_stmt (this->func_->fensure);
754 else if (s->statement)
755 this->build_stmt (s->statement);
758 /* A switch statement goes to one of a collection of case statements
759 depending on the value of the switch expression. */
761 void visit (SwitchStatement *s)
763 this->start_scope (level_switch);
764 tree lbreak = this->push_break_label (s);
766 tree condition = build_expr_dtor (s->condition);
767 Type *condtype = s->condition->type->toBasetype ();
769 /* A switch statement on a string gets turned into a library call,
770 which does a binary lookup on list of string cases. */
771 if (s->condition->type->isString ())
773 Type *etype = condtype->nextOf ()->toBasetype ();
774 libcall_fn libcall;
776 switch (etype->ty)
778 case Tchar:
779 libcall = LIBCALL_SWITCH_STRING;
780 break;
782 case Twchar:
783 libcall = LIBCALL_SWITCH_USTRING;
784 break;
786 case Tdchar:
787 libcall = LIBCALL_SWITCH_DSTRING;
788 break;
790 default:
791 ::error ("switch statement value must be an array of "
792 "some character type, not %s", etype->toChars ());
793 gcc_unreachable ();
796 /* Apparently the backend is supposed to sort and set the indexes
797 on the case array, have to change them to be usable. */
798 Type *satype = condtype->sarrayOf (s->cases->dim);
799 vec<constructor_elt, va_gc> *elms = NULL;
801 s->cases->sort ();
803 for (size_t i = 0; i < s->cases->dim; i++)
805 CaseStatement *cs = (*s->cases)[i];
806 cs->index = i;
808 if (cs->exp->op != TOKstring)
809 s->error ("case '%s' is not a string", cs->exp->toChars ());
810 else
812 tree exp = build_expr (cs->exp, true);
813 CONSTRUCTOR_APPEND_ELT (elms, size_int (i), exp);
817 /* Build static declaration to reference constructor. */
818 tree ctor = build_constructor (build_ctype (satype), elms);
819 tree decl = build_artificial_decl (TREE_TYPE (ctor), ctor);
820 TREE_READONLY (decl) = 1;
821 d_pushdecl (decl);
822 rest_of_decl_compilation (decl, 1, 0);
824 /* Pass it as a dynamic array. */
825 decl = d_array_value (build_ctype (condtype->arrayOf ()),
826 size_int (s->cases->dim),
827 build_address (decl));
829 condition = build_libcall (libcall, Type::tint32, 2, decl, condition);
831 else if (!condtype->isscalar ())
833 error ("cannot handle switch condition of type %s",
834 condtype->toChars ());
835 gcc_unreachable ();
838 condition = fold (condition);
840 /* Build LABEL_DECLs now so they can be refered to by goto case.
841 Also checking the jump from the switch to the label is allowed. */
842 if (s->cases)
844 for (size_t i = 0; i < s->cases->dim; i++)
846 CaseStatement *cs = (*s->cases)[i];
847 tree caselabel = this->lookup_label (cs);
849 /* Write cases as a series of if-then-else blocks.
850 if (condition == case)
851 goto caselabel; */
852 if (s->hasVars)
854 tree ifcase = build2 (EQ_EXPR, build_ctype (condtype),
855 condition, build_expr_dtor (cs->exp));
856 tree ifbody = fold_build1 (GOTO_EXPR, void_type_node,
857 caselabel);
858 tree cond = build_vcondition (ifcase, ifbody, void_node);
859 TREE_USED (caselabel) = 1;
860 LABEL_VARIABLE_CASE (caselabel) = 1;
861 add_stmt (cond);
864 this->check_goto (s, cs);
867 if (s->sdefault)
869 tree defaultlabel = this->lookup_label (s->sdefault);
871 /* The default label is the last 'else' block. */
872 if (s->hasVars)
874 this->do_jump (defaultlabel);
875 LABEL_VARIABLE_CASE (defaultlabel) = 1;
878 this->check_goto (s, s->sdefault);
882 /* Switch body goes in its own statement list. */
883 push_stmt_list ();
884 if (s->_body)
885 this->build_stmt (s->_body);
887 tree casebody = pop_stmt_list ();
889 /* Wrap up constructed body into a switch_expr, unless it was
890 converted to an if-then-else expression. */
891 if (s->hasVars)
892 add_stmt (casebody);
893 else
895 tree switchexpr = build2 (SWITCH_EXPR, TREE_TYPE (condition),
896 condition, casebody);
897 add_stmt (switchexpr);
898 SWITCH_ALL_CASES_P (switchexpr) = 1;
901 SWITCH_BREAK_LABEL_P (lbreak) = 1;
903 /* If the switch had any 'break' statements, emit the label now. */
904 this->pop_break_label (lbreak);
905 this->finish_scope ();
908 /* Declare the case label associated with the current SwitchStatement. */
910 void visit (CaseStatement *s)
912 /* Emit the case label. */
913 tree label = this->define_label (s);
915 if (LABEL_VARIABLE_CASE (label))
916 this->do_label (label);
917 else
919 tree casevalue;
920 if (s->exp->type->isscalar ())
921 casevalue = build_expr (s->exp);
922 else
923 casevalue = build_integer_cst (s->index, build_ctype (Type::tint32));
925 tree caselabel = build_case_label (casevalue, NULL_TREE, label);
926 add_stmt (caselabel);
929 /* Now do the body. */
930 if (s->statement)
931 this->build_stmt (s->statement);
934 /* Declare the default label associated with the current SwitchStatement. */
936 void visit (DefaultStatement *s)
938 /* Emit the default case label. */
939 tree label = this->define_label (s);
941 if (LABEL_VARIABLE_CASE (label))
942 this->do_label (label);
943 else
945 tree caselabel = build_case_label (NULL_TREE, NULL_TREE, label);
946 add_stmt (caselabel);
949 /* Now do the body. */
950 if (s->statement)
951 this->build_stmt (s->statement);
954 /* Implements 'goto default' by jumping to the label associated with
955 the DefaultStatement in a switch block. */
957 void visit (GotoDefaultStatement *s)
959 tree label = this->lookup_label (s->sw->sdefault);
960 this->do_jump (label);
963 /* Implements 'goto case' by jumping to the label associated with the
964 CaseStatement in a switch block. */
966 void visit (GotoCaseStatement *s)
968 tree label = this->lookup_label (s->cs);
969 this->do_jump (label);
972 /* Throw a SwitchError exception, called when a switch statement has
973 no DefaultStatement, yet none of the cases match. */
975 void visit (SwitchErrorStatement *s)
977 add_stmt (d_assert_call (s->loc, LIBCALL_SWITCH_ERROR));
980 /* A return statement exits the current function and supplies its return
981 value, if the return type is not void. */
983 void visit (ReturnStatement *s)
985 if (s->exp == NULL || s->exp->type->toBasetype ()->ty == Tvoid)
987 /* Return has no value. */
988 add_stmt (return_expr (NULL_TREE));
989 return;
992 TypeFunction *tf = (TypeFunction *)this->func_->type;
993 Type *type = this->func_->tintro != NULL
994 ? this->func_->tintro->nextOf () : tf->nextOf ();
996 if ((this->func_->isMain () || this->func_->isCMain ())
997 && type->toBasetype ()->ty == Tvoid)
998 type = Type::tint32;
1000 if (this->func_->nrvo_can && this->func_->nrvo_var)
1002 /* Just refer to the DECL_RESULT; this differs from using
1003 NULL_TREE in that it indicates that we care about the value
1004 of the DECL_RESULT. */
1005 tree decl = DECL_RESULT (get_symbol_decl (this->func_));
1006 add_stmt (return_expr (decl));
1008 else
1010 /* Convert for initializing the DECL_RESULT. */
1011 tree expr = build_return_dtor (s->exp, type, tf);
1012 add_stmt (expr);
1016 /* Evaluate the enclosed expression, and add it to the statement list. */
1018 void visit (ExpStatement *s)
1020 if (s->exp)
1022 /* Expression may produce temporaries requiring scope destruction. */
1023 tree exp = build_expr_dtor (s->exp);
1024 add_stmt (exp);
1028 /* Evaluate all enclosed statements. */
1030 void visit (CompoundStatement *s)
1032 if (s->statements == NULL)
1033 return;
1035 for (size_t i = 0; i < s->statements->dim; i++)
1037 Statement *statement = (*s->statements)[i];
1039 if (statement != NULL)
1040 this->build_stmt (statement);
1044 /* The frontend lowers `foreach (Tuple!(...))' statements as an unrolled loop.
1045 These are compiled down as a `do ... while (0)', where each unrolled loop
1046 is nested inside and given their own continue label to jump to. */
1048 void visit (UnrolledLoopStatement *s)
1050 if (s->statements == NULL)
1051 return;
1053 tree lbreak = this->push_break_label (s);
1054 this->start_scope (level_loop);
1056 for (size_t i = 0; i < s->statements->dim; i++)
1058 Statement *statement = (*s->statements)[i];
1060 if (statement != NULL)
1062 tree lcontinue = this->push_continue_label (statement);
1063 this->build_stmt (statement);
1064 this->pop_continue_label (lcontinue);
1068 this->do_jump (this->break_label_);
1070 tree body = this->end_scope ();
1071 add_stmt (build1 (LOOP_EXPR, void_type_node, body));
1073 this->pop_break_label (lbreak);
1076 /* Start a new scope and visit all nested statements, wrapping
1077 them up into a BIND_EXPR at the end of the scope. */
1079 void visit (ScopeStatement *s)
1081 if (s->statement == NULL)
1082 return;
1084 this->start_scope (level_block);
1085 this->build_stmt (s->statement);
1086 this->finish_scope ();
1089 /* A with statement is a way to simplify repeated references to the same
1090 object, where the handle is either a class or struct instance. */
1092 void visit (WithStatement *s)
1094 this->start_scope (level_with);
1096 if (s->wthis)
1098 /* Perform initialisation of the 'with' handle. */
1099 ExpInitializer *ie = s->wthis->_init->isExpInitializer ();
1100 gcc_assert (ie != NULL);
1102 declare_local_var (s->wthis);
1103 tree init = build_expr_dtor (ie->exp);
1104 add_stmt (init);
1107 if (s->_body)
1108 this->build_stmt (s->_body);
1110 this->finish_scope ();
1113 /* Implements 'throw Object'. Frontend already checks that the object
1114 thrown is a class type, but does not check if it is derived from
1115 Object. Foreign objects are not currently supported at run-time. */
1117 void visit (ThrowStatement *s)
1119 ClassDeclaration *cd = s->exp->type->toBasetype ()->isClassHandle ();
1120 InterfaceDeclaration *id = cd->isInterfaceDeclaration ();
1121 tree arg = build_expr_dtor (s->exp);
1123 if (!flag_exceptions)
1125 static int warned = 0;
1126 if (!warned)
1128 error_at (make_location_t (s->loc), "exception handling disabled, "
1129 "use -fexceptions to enable");
1130 warned = 1;
1134 if (cd->isCPPclass () || (id != NULL && id->isCPPclass ()))
1135 error_at (make_location_t (s->loc), "cannot throw C++ classes");
1136 else if (cd->com || (id != NULL && id->com))
1137 error_at (make_location_t (s->loc), "cannot throw COM objects");
1138 else
1139 arg = build_nop (build_ctype (get_object_type ()), arg);
1141 add_stmt (build_libcall (LIBCALL_THROW, Type::tvoid, 1, arg));
1144 /* Build a try-catch statement, one of the building blocks for exception
1145 handling generated by the frontend. This is also used to implement
1146 `scope (failure)' statements. */
1148 void visit (TryCatchStatement *s)
1150 this->start_scope (level_try);
1151 if (s->_body)
1152 this->build_stmt (s->_body);
1154 tree trybody = this->end_scope ();
1156 /* Try handlers go in their own statement list. */
1157 push_stmt_list ();
1159 if (s->catches)
1161 for (size_t i = 0; i < s->catches->dim; i++)
1163 Catch *vcatch = (*s->catches)[i];
1165 this->start_scope (level_catch);
1167 tree ehptr = builtin_decl_explicit (BUILT_IN_EH_POINTER);
1168 tree catchtype = build_ctype (vcatch->type);
1169 tree object = NULL_TREE;
1171 ehptr = build_call_expr (ehptr, 1, integer_zero_node);
1173 /* Retrieve the internal exception object, which could be for a
1174 D or C++ catch handler. This is different from the generic
1175 exception pointer returned from gcc runtime. */
1176 Type *tcatch = vcatch->type->toBasetype ();
1177 ClassDeclaration *cd = tcatch->isClassHandle ();
1179 libcall_fn libcall = (cd->isCPPclass ()) ? LIBCALL_CXA_BEGIN_CATCH
1180 : LIBCALL_BEGIN_CATCH;
1181 object = build_libcall (libcall, vcatch->type, 1, ehptr);
1183 if (vcatch->var)
1185 tree var = get_symbol_decl (vcatch->var);
1186 tree init = build_assign (INIT_EXPR, var, object);
1188 declare_local_var (vcatch->var);
1189 add_stmt (init);
1191 else
1193 /* Still need to emit a call to __gdc_begin_catch() to
1194 remove the object from the uncaught exceptions list. */
1195 add_stmt (object);
1198 if (vcatch->handler)
1199 this->build_stmt (vcatch->handler);
1201 tree catchbody = this->end_scope ();
1203 /* Need to wrap C++ handlers in a try/finally block to signal
1204 the end catch callback. */
1205 if (cd->isCPPclass ())
1207 tree endcatch = build_libcall (LIBCALL_CXA_END_CATCH,
1208 Type::tvoid, 0);
1209 catchbody = build2 (TRY_FINALLY_EXPR, void_type_node,
1210 catchbody, endcatch);
1213 add_stmt (build2 (CATCH_EXPR, void_type_node,
1214 catchtype, catchbody));
1218 tree catches = pop_stmt_list ();
1220 /* Back-end expects all catches in a TRY_CATCH_EXPR to be enclosed in a
1221 statement list, however pop_stmt_list may optimize away the list
1222 if there is only a single catch to push. */
1223 if (TREE_CODE (catches) != STATEMENT_LIST)
1225 tree stmt_list = alloc_stmt_list ();
1226 append_to_statement_list_force (catches, &stmt_list);
1227 catches = stmt_list;
1230 add_stmt (build2 (TRY_CATCH_EXPR, void_type_node, trybody, catches));
1233 /* Build a try-finally statement, one of the building blocks for exception
1234 handling generated by the frontend. This is also used to implement
1235 `scope (exit)' statements. */
1237 void visit (TryFinallyStatement *s)
1239 this->start_scope (level_try);
1240 if (s->_body)
1241 this->build_stmt (s->_body);
1243 tree trybody = this->end_scope ();
1245 this->start_scope (level_finally);
1246 if (s->finalbody)
1247 this->build_stmt (s->finalbody);
1249 tree finally = this->end_scope ();
1251 add_stmt (build2 (TRY_FINALLY_EXPR, void_type_node, trybody, finally));
1254 /* The frontend lowers `synchronized (...)' statements as a call to
1255 monitor/critical enter and exit wrapped around try/finally.
1256 This visitor is not strictly required other than to enforce that
1257 these kinds of statements never reach here. */
1259 void visit (SynchronizedStatement *)
1261 gcc_unreachable ();
1264 /* D Inline Assembler is not implemented, as it would require writing
1265 an assembly parser for each supported target. Instead we leverage
1266 GCC extended assembler using the GccAsmStatement class. */
1268 void visit (AsmStatement *)
1270 sorry ("D inline assembler statements are not supported in GDC.");
1273 /* Build a GCC extended assembler expression, whose components are
1274 an INSN string, some OUTPUTS, some INPUTS, and some CLOBBERS. */
1276 void visit (GccAsmStatement *s)
1278 StringExp *insn = (StringExp *)s->insn;
1279 tree outputs = NULL_TREE;
1280 tree inputs = NULL_TREE;
1281 tree clobbers = NULL_TREE;
1282 tree labels = NULL_TREE;
1284 /* Collect all arguments, which may be input or output operands. */
1285 if (s->args)
1287 for (size_t i = 0; i < s->args->dim; i++)
1289 Identifier *name = (*s->names)[i];
1290 const char *sname = name ? name->toChars () : NULL;
1291 tree id = name ? build_string (strlen (sname), sname) : NULL_TREE;
1293 StringExp *constr = (StringExp *)(*s->constraints)[i];
1294 const char *cstring = (const char *)(constr->len
1295 ? constr->string : "");
1296 tree str = build_string (constr->len, cstring);
1298 Expression *earg = (*s->args)[i];
1299 tree val = build_expr (earg);
1301 if (i < s->outputargs)
1303 tree arg = build_tree_list (id, str);
1304 outputs = chainon (outputs, build_tree_list (arg, val));
1306 else
1308 tree arg = build_tree_list (id, str);
1309 inputs = chainon (inputs, build_tree_list (arg, val));
1314 /* Collect all clobber arguments. */
1315 if (s->clobbers)
1317 for (size_t i = 0; i < s->clobbers->dim; i++)
1319 StringExp *clobber = (StringExp *)(*s->clobbers)[i];
1320 const char *cstring = (const char *)(clobber->len
1321 ? clobber->string : "");
1323 tree val = build_string (clobber->len, cstring);
1324 clobbers = chainon (clobbers, build_tree_list (0, val));
1328 /* Collect all goto labels, these should have been already checked
1329 by the front-end, so pass down the label symbol to the back-end. */
1330 if (s->labels)
1332 for (size_t i = 0; i < s->labels->dim; i++)
1334 Identifier *ident = (*s->labels)[i];
1335 GotoStatement *gs = (*s->gotos)[i];
1337 gcc_assert (gs->label->statement != NULL);
1338 gcc_assert (gs->tf == gs->label->statement->tf);
1340 const char *sident = ident->toChars ();
1341 tree name = build_string (strlen (sident), sident);
1342 tree label = this->lookup_label (gs->label->statement,
1343 gs->label->ident);
1344 TREE_USED (label) = 1;
1346 labels = chainon (labels, build_tree_list (name, label));
1350 /* Do some extra validation on all input and output operands. */
1351 const char *insnstring = (const char *)(insn->len ? insn->string : "");
1352 tree string = build_string (insn->len, insnstring);
1353 string = resolve_asm_operand_names (string, outputs, inputs, labels);
1355 if (s->args)
1357 unsigned noutputs = s->outputargs;
1358 unsigned ninputs = (s->args->dim - noutputs);
1359 const char **oconstraints = XALLOCAVEC (const char *, noutputs);
1360 bool allows_mem, allows_reg, is_inout;
1361 size_t i;
1362 tree t;
1364 for (i = 0, t = outputs; t != NULL_TREE; t = TREE_CHAIN (t), i++)
1366 tree output = TREE_VALUE (t);
1367 const char *constraint
1368 = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
1370 oconstraints[i] = constraint;
1372 if (parse_output_constraint (&constraint, i, ninputs, noutputs,
1373 &allows_mem, &allows_reg, &is_inout))
1375 /* If the output argument is going to end up in memory. */
1376 if (!allows_reg)
1377 d_mark_addressable (output);
1379 else
1380 output = error_mark_node;
1382 TREE_VALUE (t) = output;
1385 for (i = 0, t = inputs; t != NULL_TREE; t = TREE_CHAIN (t), i++)
1387 tree input = TREE_VALUE (t);
1388 const char *constraint
1389 = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
1391 if (parse_input_constraint (&constraint, i, ninputs, noutputs, 0,
1392 oconstraints, &allows_mem, &allows_reg))
1394 /* If the input argument is going to end up in memory. */
1395 if (!allows_reg && allows_mem)
1396 d_mark_addressable (input);
1398 else
1399 input = error_mark_node;
1401 TREE_VALUE (t) = input;
1405 tree exp = build5 (ASM_EXPR, void_type_node, string,
1406 outputs, inputs, clobbers, labels);
1407 SET_EXPR_LOCATION (exp, make_location_t (s->loc));
1409 /* If the extended syntax was not used, mark the ASM_EXPR. */
1410 if (s->args == NULL && s->clobbers == NULL)
1411 ASM_INPUT_P (exp) = 1;
1413 /* Asm statements are treated as volatile unless 'pure'. */
1414 ASM_VOLATILE_P (exp) = !(s->stc & STCpure);
1416 add_stmt (exp);
1419 /* Import symbols from another module. */
1421 void visit (ImportStatement *s)
1423 if (s->imports == NULL)
1424 return;
1426 for (size_t i = 0; i < s->imports->dim; i++)
1428 Dsymbol *dsym = (*s->imports)[i];
1430 if (dsym != NULL)
1431 build_decl_tree (dsym);
1436 /* Main entry point for the IRVisitor interface to generate
1437 code for the body of function FD. */
1439 void
1440 build_function_body (FuncDeclaration *fd)
1442 IRVisitor v = IRVisitor (fd);
1443 location_t saved_location = input_location;
1444 input_location = make_location_t (fd->loc);
1445 v.build_stmt (fd->fbody);
1446 input_location = saved_location;