1 /* toir.cc -- Lower D frontend statements to GCC trees.
2    Copyright (C) 2006-2019 Free Software Foundation, Inc.
3 
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.
8 
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.
13 
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/>.  */
17 
18 #include "config.h"
19 #include "system.h"
20 #include "coretypes.h"
21 
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"
28 
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"
38 
39 #include "d-tree.h"
40 
41 
42 /* Update data for defined and undefined labels when leaving a scope.  */
43 
44 bool
pop_binding_label(Statement * const &,d_label_entry * ent,binding_level * bl)45 pop_binding_label (Statement * const &, d_label_entry *ent, binding_level *bl)
46 {
47   binding_level *obl = bl->level_chain;
48 
49   if (ent->level == bl)
50     {
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;
55 
56       ent->level = obl;
57     }
58   else if (ent->fwdrefs)
59     {
60       for (d_label_use_entry *ref = ent->fwdrefs; ref; ref = ref->next)
61 	ref->level = obl;
62     }
63 
64   return true;
65 }
66 
67 /* At the end of a function, all labels declared within the function
68    go out of scope.  Queue them in LABELS.  */
69 
70 bool
pop_label(Statement * const &,d_label_entry * ent,vec<tree> & labels)71 pop_label (Statement * const &, d_label_entry *ent, vec<tree> &labels)
72 {
73   if (!ent->bc_label)
74     {
75       /* Put the labels into the "variables" of the top-level block,
76 	 so debugger can see them.  */
77       if (DECL_NAME (ent->label))
78 	{
79 	  gcc_assert (DECL_INITIAL (ent->label) != NULL_TREE);
80 	  labels.safe_push (ent->label);
81 	}
82     }
83 
84   return true;
85 }
86 
87 /* The D front-end does not use the 'binding level' system for a symbol table,
88    however it has been the goto structure for tracking code flow.
89    Primarily it is only needed to get debugging information for local variables
90    and otherwise support the back-end.  */
91 
92 void
push_binding_level(level_kind kind)93 push_binding_level (level_kind kind)
94 {
95   /* Add it to the front of currently active scopes stack.  */
96   binding_level *new_level = ggc_cleared_alloc<binding_level> ();
97   new_level->level_chain = current_binding_level;
98   new_level->kind = kind;
99 
100   current_binding_level = new_level;
101 }
102 
103 static int
cmp_labels(const void * p1,const void * p2)104 cmp_labels (const void *p1, const void *p2)
105 {
106   const tree *l1 = (const tree *)p1;
107   const tree *l2 = (const tree *)p2;
108   return DECL_UID (*l1) - DECL_UID (*l2);
109 }
110 
111 tree
pop_binding_level(void)112 pop_binding_level (void)
113 {
114   binding_level *level = current_binding_level;
115   current_binding_level = level->level_chain;
116 
117   tree block = make_node (BLOCK);
118   BLOCK_VARS (block) = level->names;
119   BLOCK_SUBBLOCKS (block) = level->blocks;
120 
121   /* In each subblock, record that this is its superior.  */
122   for (tree t = level->blocks; t; t = BLOCK_CHAIN (t))
123     BLOCK_SUPERCONTEXT (t) = block;
124 
125   if (level->kind == level_function)
126     {
127       /* Dispose of the block that we just made inside some higher level.  */
128       DECL_INITIAL (current_function_decl) = block;
129       BLOCK_SUPERCONTEXT (block) = current_function_decl;
130 
131       /* Pop all the labels declared in the function.  */
132       if (d_function_chain->labels)
133 	{
134 	  auto_vec<tree> labels;
135 	  d_function_chain->labels->traverse<vec<tree> &, &pop_label> (labels);
136 	  d_function_chain->labels->empty ();
137 	  labels.qsort (cmp_labels);
138 	  for (unsigned i = 0; i < labels.length (); ++i)
139 	    {
140 	      DECL_CHAIN (labels[i]) = BLOCK_VARS (block);
141 	      BLOCK_VARS (block) = labels[i];
142 	    }
143 	}
144     }
145   else
146     {
147       /* Any uses of undefined labels, and any defined labels, now operate
148 	 under constraints of next binding contour.  */
149       if (d_function_chain && d_function_chain->labels)
150 	{
151 	  language_function *f = d_function_chain;
152 	  f->labels->traverse<binding_level *, &pop_binding_label> (level);
153 	}
154 
155       current_binding_level->blocks
156 	= block_chainon (current_binding_level->blocks, block);
157     }
158 
159   TREE_USED (block) = 1;
160   return block;
161 }
162 
163 /* Create an empty statement tree rooted at T.  */
164 
165 void
push_stmt_list(void)166 push_stmt_list (void)
167 {
168   tree t = alloc_stmt_list ();
169   vec_safe_push (d_function_chain->stmt_list, t);
170   d_keep (t);
171 }
172 
173 /* Finish the statement tree rooted at T.  */
174 
175 tree
pop_stmt_list(void)176 pop_stmt_list (void)
177 {
178   tree t = d_function_chain->stmt_list->pop ();
179 
180   /* If the statement list is completely empty, just return it.  This is just
181      as good as build_empty_stmt, with the advantage that statement lists
182      are merged when they are appended to one another.  So using the
183      STATEMENT_LIST avoids pathological buildup of EMPTY_STMT_P statements.  */
184   if (TREE_SIDE_EFFECTS (t))
185     {
186       /* If the statement list contained exactly one statement, then extract
187 	 it immediately.  */
188       tree_stmt_iterator i = tsi_start (t);
189 
190       if (tsi_one_before_end_p (i))
191 	{
192 	  tree u = tsi_stmt (i);
193 	  tsi_delink (&i);
194 	  free_stmt_list (t);
195 	  t = u;
196 	}
197     }
198 
199   return t;
200 }
201 
202 /* T is an expression statement.  Add it to the statement-tree.  */
203 
204 void
add_stmt(tree t)205 add_stmt (tree t)
206 {
207   /* Ignore (void) 0; expression statements received from the frontend.
208      Likewise void_node is used when contracts become nops in release code.  */
209   if (t == void_node || IS_EMPTY_STMT (t))
210     return;
211 
212   /* At this point, we no longer care about the value of expressions,
213      so if there's no side-effects, then don't add it.  */
214   if (!TREE_SIDE_EFFECTS (t))
215     return;
216 
217   if (TREE_CODE (t) == COMPOUND_EXPR)
218     {
219       /* Push out each comma expressions as separate statements.  */
220       add_stmt (TREE_OPERAND (t, 0));
221       add_stmt (TREE_OPERAND (t, 1));
222     }
223   else
224     {
225       /* Force the type to be void so we don't need to create a temporary
226 	 variable to hold the inner expression.  */
227       if (TREE_CODE (t) == CLEANUP_POINT_EXPR)
228 	TREE_TYPE (t) = void_type_node;
229 
230       /* Append the expression to the statement list.
231 	 Make sure it has a proper location.  */
232       if (EXPR_P (t) && !EXPR_HAS_LOCATION (t))
233 	SET_EXPR_LOCATION (t, input_location);
234 
235       tree stmt_list = d_function_chain->stmt_list->last ();
236       append_to_statement_list_force (t, &stmt_list);
237     }
238 }
239 
240 /* Implements the visitor interface to build the GCC trees of all Statement
241    AST classes emitted from the D Front-end.
242    All visit methods accept one parameter S, which holds the frontend AST
243    of the statement to compile.  They also don't return any value, instead
244    generated code are pushed to add_stmt(), which appends them to the
245    statement list in the current_binding_level.  */
246 
247 class IRVisitor : public Visitor
248 {
249   using Visitor::visit;
250 
251   FuncDeclaration *func_;
252 
253   /* Stack of labels which are targets for "break" and "continue",
254      linked through TREE_CHAIN.  */
255   tree break_label_;
256   tree continue_label_;
257 
258 public:
IRVisitor(FuncDeclaration * fd)259   IRVisitor (FuncDeclaration *fd)
260   {
261     this->func_ = fd;
262     this->break_label_ = NULL_TREE;
263     this->continue_label_ = NULL_TREE;
264   }
265 
266   /* Helper for generating code for the statement AST class S.
267      Sets up the location of the statement before lowering.  */
268 
build_stmt(Statement * s)269   void build_stmt (Statement *s)
270   {
271     location_t saved_location = input_location;
272     input_location = make_location_t (s->loc);
273     s->accept (this);
274     input_location = saved_location;
275   }
276 
277   /* Start a new scope for a KIND statement.
278      Each user-declared variable will have a binding contour that begins
279      where the variable is declared and ends at its containing scope.  */
280 
start_scope(level_kind kind)281   void start_scope (level_kind kind)
282   {
283     push_binding_level (kind);
284     push_stmt_list ();
285   }
286 
287   /* Leave scope pushed by start_scope, returning a new bind_expr if
288      any variables where declared in the scope.  */
289 
end_scope(void)290   tree end_scope (void)
291   {
292     tree block = pop_binding_level ();
293     tree body = pop_stmt_list ();
294 
295     if (! BLOCK_VARS (block))
296       return body;
297 
298     tree bind = build3 (BIND_EXPR, void_type_node,
299 			BLOCK_VARS (block), body, block);
300     TREE_SIDE_EFFECTS (bind) = 1;
301     return bind;
302   }
303 
304   /* Like end_scope, but also push it into the outer statement-tree.  */
305 
finish_scope(void)306   void finish_scope (void)
307   {
308     tree scope = this->end_scope ();
309     add_stmt (scope);
310   }
311 
312   /* Return TRUE if IDENT is the current function return label.  */
313 
is_return_label(Identifier * ident)314   bool is_return_label (Identifier *ident)
315   {
316     if (this->func_->returnLabel)
317       return this->func_->returnLabel->ident == ident;
318 
319     return false;
320   }
321 
322   /* Define a label, specifying the location in the source file.
323      Return the LABEL_DECL node for the label.  */
324 
define_label(Statement * s,Identifier * ident=NULL)325   tree define_label (Statement *s, Identifier *ident = NULL)
326   {
327     tree label = this->lookup_label (s, ident);
328     gcc_assert (DECL_INITIAL (label) == NULL_TREE);
329 
330     d_label_entry *ent = d_function_chain->labels->get (s);
331     gcc_assert (ent != NULL);
332 
333     /* Mark label as having been defined.  */
334     DECL_INITIAL (label) = error_mark_node;
335 
336     ent->level = current_binding_level;
337 
338     for (d_label_use_entry *ref = ent->fwdrefs; ref ; ref = ref->next)
339       this->check_previous_goto (ent->statement, ref);
340     ent->fwdrefs = NULL;
341 
342     return label;
343   }
344 
345   /* Emit a LABEL expression.  */
346 
do_label(tree label)347   void do_label (tree label)
348   {
349     /* Don't write out label unless it is marked as used by the frontend.
350        This makes auto-vectorization possible in conditional loops.
351        The only excemption to this is in the LabelStatement visitor,
352        in which all computed labels are marked regardless.  */
353     if (TREE_USED (label))
354       add_stmt (build1 (LABEL_EXPR, void_type_node, label));
355   }
356 
357   /* Emit a goto expression to LABEL.  */
358 
do_jump(tree label)359   void do_jump (tree label)
360   {
361     add_stmt (fold_build1 (GOTO_EXPR, void_type_node, label));
362     TREE_USED (label) = 1;
363   }
364 
365   /* Check that a new jump at statement scope FROM to a label declared in
366      statement scope TO is valid.  */
367 
check_goto(Statement * from,Statement * to)368   void check_goto (Statement *from, Statement *to)
369   {
370     d_label_entry *ent = d_function_chain->labels->get (to);
371     gcc_assert (ent != NULL);
372 
373     /* If the label hasn't been defined yet, defer checking.  */
374     if (! DECL_INITIAL (ent->label))
375       {
376 	d_label_use_entry *fwdref = ggc_alloc<d_label_use_entry> ();
377 	fwdref->level = current_binding_level;
378 	fwdref->statement = from;
379 	fwdref->next = ent->fwdrefs;
380 	ent->fwdrefs = fwdref;
381 	return;
382       }
383 
384     if (ent->in_try_scope)
385       error_at (make_location_t (from->loc), "cannot goto into try block");
386     else if (ent->in_catch_scope)
387       error_at (make_location_t (from->loc), "cannot goto into catch block");
388   }
389 
390   /* Check that a previously seen jump to a newly defined label is valid.
391      S is the label statement; FWDREF is the jump context.  This is called
392      for both user-defined and case labels.  */
393 
check_previous_goto(Statement * s,d_label_use_entry * fwdref)394   void check_previous_goto (Statement *s, d_label_use_entry *fwdref)
395   {
396     for (binding_level *b = current_binding_level; b ; b = b->level_chain)
397       {
398 	if (b == fwdref->level)
399 	  break;
400 
401 	if (b->kind == level_try || b->kind == level_catch)
402 	  {
403 	    location_t location;
404 
405 	    if (s->isLabelStatement ())
406 	      {
407 		location = make_location_t (fwdref->statement->loc);
408 		if (b->kind == level_try)
409 		  error_at (location, "cannot goto into try block");
410 		else
411 		  error_at (location, "cannot goto into catch block");
412 	      }
413 	    else if (s->isCaseStatement ())
414 	      {
415 		location = make_location_t (s->loc);
416 		error_at (location, "case cannot be in different "
417 			  "try block level from switch");
418 	      }
419 	    else if (s->isDefaultStatement ())
420 	      {
421 		location = make_location_t (s->loc);
422 		error_at (location, "default cannot be in different "
423 			  "try block level from switch");
424 	      }
425 	    else
426 	      gcc_unreachable ();
427 	  }
428       }
429   }
430 
431   /* Get or build LABEL_DECL using the IDENT and statement block S given.  */
432 
lookup_label(Statement * s,Identifier * ident=NULL)433   tree lookup_label (Statement *s, Identifier *ident = NULL)
434   {
435     /* You can't use labels at global scope.  */
436     if (d_function_chain == NULL)
437       {
438 	error ("label %s referenced outside of any function",
439 	       ident ? ident->toChars () : "(unnamed)");
440 	return NULL_TREE;
441       }
442 
443     /* Create the label htab for the function on demand.  */
444     if (!d_function_chain->labels)
445       {
446 	d_function_chain->labels
447 	  = hash_map<Statement *, d_label_entry>::create_ggc (13);
448       }
449 
450     d_label_entry *ent = d_function_chain->labels->get (s);
451     if (ent != NULL)
452       return ent->label;
453     else
454       {
455 	tree name = ident ? get_identifier (ident->toChars ()) : NULL_TREE;
456 	tree decl = build_decl (make_location_t (s->loc), LABEL_DECL,
457 				name, void_type_node);
458 	DECL_CONTEXT (decl) = current_function_decl;
459 	DECL_MODE (decl) = VOIDmode;
460 
461 	/* Create new empty slot.  */
462 	ent = ggc_cleared_alloc<d_label_entry> ();
463 	ent->statement = s;
464 	ent->label = decl;
465 
466 	bool existed = d_function_chain->labels->put (s, *ent);
467 	gcc_assert (!existed);
468 
469 	return decl;
470       }
471   }
472 
473   /* Get the LABEL_DECL to represent a break or continue for the
474      statement S given.  BC indicates which.  */
475 
lookup_bc_label(Statement * s,bc_kind bc)476   tree lookup_bc_label (Statement *s, bc_kind bc)
477   {
478     tree vec = this->lookup_label (s);
479 
480     /* The break and continue labels are put into a TREE_VEC.  */
481     if (TREE_CODE (vec) == LABEL_DECL)
482       {
483 	d_label_entry *ent = d_function_chain->labels->get (s);
484 	gcc_assert (ent != NULL);
485 
486 	vec = make_tree_vec (2);
487 	TREE_VEC_ELT (vec, bc_break) = ent->label;
488 
489 	/* Build the continue label.  */
490 	tree label = build_decl (make_location_t (s->loc), LABEL_DECL,
491 				 NULL_TREE, void_type_node);
492 	DECL_CONTEXT (label) = current_function_decl;
493 	DECL_MODE (label) = VOIDmode;
494 	TREE_VEC_ELT (vec, bc_continue) = label;
495 
496 	ent->label = vec;
497 	ent->bc_label = true;
498       }
499 
500     return TREE_VEC_ELT (vec, bc);
501   }
502 
503   /* Set and return the current break label for the current block.  */
504 
push_break_label(Statement * s)505   tree push_break_label (Statement *s)
506   {
507     tree label = this->lookup_bc_label (s->getRelatedLabeled (), bc_break);
508     DECL_CHAIN (label) = this->break_label_;
509     this->break_label_ = label;
510     return label;
511   }
512 
513   /* Finish with the current break label.  */
514 
pop_break_label(tree label)515   void pop_break_label (tree label)
516   {
517     gcc_assert (this->break_label_ == label);
518     this->break_label_ = DECL_CHAIN (this->break_label_);
519     this->do_label (label);
520   }
521 
522   /* Set and return the continue label for the current block.  */
523 
push_continue_label(Statement * s)524   tree push_continue_label (Statement *s)
525   {
526     tree label = this->lookup_bc_label (s->getRelatedLabeled (), bc_continue);
527     DECL_CHAIN (label) = this->continue_label_;
528     this->continue_label_ = label;
529     return label;
530   }
531 
532   /* Finish with the current continue label.  */
533 
pop_continue_label(tree label)534   void pop_continue_label (tree label)
535   {
536     gcc_assert (this->continue_label_ == label);
537     this->continue_label_ = DECL_CHAIN (this->continue_label_);
538     this->do_label (label);
539   }
540 
541   /* Visitor interfaces.  */
542 
543 
544   /* This should be overridden by each statement class.  */
545 
visit(Statement *)546   void visit (Statement *)
547   {
548     gcc_unreachable ();
549   }
550 
551   /* The frontend lowers `scope (exit/failure/success)' statements as
552      try/catch/finally.  At this point, this statement is just an empty
553      placeholder.  Maybe the frontend shouldn't leak these.  */
554 
visit(OnScopeStatement *)555   void visit (OnScopeStatement *)
556   {
557   }
558 
559   /* If statements provide simple conditional execution of statements.  */
560 
visit(IfStatement * s)561   void visit (IfStatement *s)
562   {
563     this->start_scope (level_cond);
564 
565     /* Build the outer 'if' condition, which may produce temporaries
566        requiring scope destruction.  */
567     tree ifcond = convert_for_condition (build_expr_dtor (s->condition),
568 					 s->condition->type);
569     tree ifbody = void_node;
570     tree elsebody = void_node;
571 
572     /* Build the 'then' branch.  */
573     if (s->ifbody)
574       {
575 	push_stmt_list ();
576 	this->build_stmt (s->ifbody);
577 	ifbody = pop_stmt_list ();
578       }
579 
580     /* Now build the 'else' branch, which may have nested 'else if' parts.  */
581     if (s->elsebody)
582       {
583 	push_stmt_list ();
584 	this->build_stmt (s->elsebody);
585 	elsebody = pop_stmt_list ();
586       }
587 
588     /* Wrap up our constructed if condition into a COND_EXPR.  */
589     tree cond = build_vcondition (ifcond, ifbody, elsebody);
590     add_stmt (cond);
591 
592     /* Finish the if-then scope.  */
593     this->finish_scope ();
594   }
595 
596   /* Should there be any `pragma (...)' statements requiring code generation,
597      here would be the place to do it.  For now, all pragmas are handled
598      by the frontend.  */
599 
visit(PragmaStatement *)600   void visit (PragmaStatement *)
601   {
602   }
603 
604   /* The frontend lowers `while (...)' statements as `for (...)' loops.
605      This visitor is not strictly required other than to enforce that
606      these kinds of statements never reach here.  */
607 
visit(WhileStatement *)608   void visit (WhileStatement *)
609   {
610     gcc_unreachable ();
611   }
612 
613   /* Do while statments implement simple loops.  The body is executed, then
614      the condition is evaluated.  */
615 
visit(DoStatement * s)616   void visit (DoStatement *s)
617   {
618     tree lbreak = this->push_break_label (s);
619 
620     this->start_scope (level_loop);
621     if (s->_body)
622       {
623 	tree lcontinue = this->push_continue_label (s);
624 	this->build_stmt (s->_body);
625 	this->pop_continue_label (lcontinue);
626       }
627 
628     /* Build the outer 'while' condition, which may produce temporaries
629        requiring scope destruction.  */
630     tree exitcond = convert_for_condition (build_expr_dtor (s->condition),
631 					   s->condition->type);
632     add_stmt (build_vcondition (exitcond, void_node,
633 				build1 (GOTO_EXPR, void_type_node, lbreak)));
634     TREE_USED (lbreak) = 1;
635 
636     tree body = this->end_scope ();
637     add_stmt (build1 (LOOP_EXPR, void_type_node, body));
638 
639     this->pop_break_label (lbreak);
640   }
641 
642   /* For statements implement loops with initialization, test, and
643      increment clauses.  */
644 
visit(ForStatement * s)645   void visit (ForStatement *s)
646   {
647     tree lbreak = this->push_break_label (s);
648     this->start_scope (level_loop);
649 
650     if (s->_init)
651       this->build_stmt (s->_init);
652 
653     if (s->condition)
654       {
655 	tree exitcond = convert_for_condition (build_expr_dtor (s->condition),
656 					       s->condition->type);
657 	add_stmt (build_vcondition (exitcond, void_node,
658 				    build1 (GOTO_EXPR, void_type_node,
659 					    lbreak)));
660 	TREE_USED (lbreak) = 1;
661       }
662 
663     if (s->_body)
664       {
665 	tree lcontinue = this->push_continue_label (s);
666 	this->build_stmt (s->_body);
667 	this->pop_continue_label (lcontinue);
668       }
669 
670     if (s->increment)
671       {
672 	/* Force side effects?  */
673 	add_stmt (build_expr_dtor (s->increment));
674       }
675 
676     tree body = this->end_scope ();
677     add_stmt (build1 (LOOP_EXPR, void_type_node, body));
678 
679     this->pop_break_label (lbreak);
680   }
681 
682   /* The frontend lowers `foreach (...)' statements as `for (...)' loops.
683      This visitor is not strictly required other than to enforce that
684      these kinds of statements never reach here.  */
685 
visit(ForeachStatement *)686   void visit (ForeachStatement *)
687   {
688     gcc_unreachable ();
689   }
690 
691   /* The frontend lowers `foreach (...; [x..y])' statements as `for (...)'
692      loops.  This visitor is not strictly required other than to enforce that
693      these kinds of statements never reach here.  */
694 
visit(ForeachRangeStatement *)695   void visit (ForeachRangeStatement *)
696   {
697     gcc_unreachable ();
698   }
699 
700   /* Jump to the associated exit label for the current loop.  If IDENT
701      for the Statement is not null, then the label is user defined.  */
702 
visit(BreakStatement * s)703   void visit (BreakStatement *s)
704   {
705     if (s->ident)
706       {
707 	/* The break label may actually be some levels up.
708 	   eg: on a try/finally wrapping a loop.  */
709 	LabelStatement *label = this->func_->searchLabel (s->ident)->statement;
710 	gcc_assert (label != NULL);
711 	Statement *stmt = label->statement->getRelatedLabeled ();
712 	this->do_jump (this->lookup_bc_label (stmt, bc_break));
713       }
714     else
715       this->do_jump (this->break_label_);
716   }
717 
718   /* Jump to the associated continue label for the current loop.  If IDENT
719      for the Statement is not null, then the label is user defined.  */
720 
visit(ContinueStatement * s)721   void visit (ContinueStatement *s)
722   {
723     if (s->ident)
724       {
725 	LabelStatement *label = this->func_->searchLabel (s->ident)->statement;
726 	gcc_assert (label != NULL);
727 	this->do_jump (this->lookup_bc_label (label->statement,
728 					      bc_continue));
729       }
730     else
731       this->do_jump (this->continue_label_);
732   }
733 
734   /* A goto statement jumps to the statement identified by the given label.  */
735 
visit(GotoStatement * s)736   void visit (GotoStatement *s)
737   {
738     gcc_assert (s->label->statement != NULL);
739     gcc_assert (s->tf == s->label->statement->tf);
740 
741     /* If no label found, there was an error.  */
742     tree label = this->lookup_label (s->label->statement, s->label->ident);
743     this->do_jump (label);
744 
745     /* Need to error if the goto is jumping into a try or catch block.  */
746     this->check_goto (s, s->label->statement);
747   }
748 
749   /* Statements can be labeled.  A label is an identifier that precedes
750      a statement.  */
751 
visit(LabelStatement * s)752   void visit (LabelStatement *s)
753   {
754     LabelDsymbol *sym;
755 
756     if (this->is_return_label (s->ident))
757       sym = this->func_->returnLabel;
758     else
759       sym = this->func_->searchLabel (s->ident);
760 
761     /* If no label found, there was an error.  */
762     tree label = this->define_label (sym->statement, sym->ident);
763     TREE_USED (label) = 1;
764 
765     this->do_label (label);
766 
767     if (this->is_return_label (s->ident) && this->func_->fensure != NULL)
768       this->build_stmt (this->func_->fensure);
769     else if (s->statement)
770       this->build_stmt (s->statement);
771   }
772 
773   /* A switch statement goes to one of a collection of case statements
774      depending on the value of the switch expression.  */
775 
visit(SwitchStatement * s)776   void visit (SwitchStatement *s)
777   {
778     this->start_scope (level_switch);
779     tree lbreak = this->push_break_label (s);
780 
781     tree condition = build_expr_dtor (s->condition);
782     Type *condtype = s->condition->type->toBasetype ();
783 
784     /* A switch statement on a string gets turned into a library call,
785        which does a binary lookup on list of string cases.  */
786     if (s->condition->type->isString ())
787       {
788 	Type *etype = condtype->nextOf ()->toBasetype ();
789 	libcall_fn libcall;
790 
791 	switch (etype->ty)
792 	  {
793 	  case Tchar:
794 	    libcall = LIBCALL_SWITCH_STRING;
795 	    break;
796 
797 	  case Twchar:
798 	    libcall = LIBCALL_SWITCH_USTRING;
799 	    break;
800 
801 	  case Tdchar:
802 	    libcall = LIBCALL_SWITCH_DSTRING;
803 	    break;
804 
805 	  default:
806 	    ::error ("switch statement value must be an array of "
807 		     "some character type, not %s", etype->toChars ());
808 	    gcc_unreachable ();
809 	  }
810 
811 	/* Apparently the backend is supposed to sort and set the indexes
812 	   on the case array, have to change them to be usable.  */
813 	Type *satype = condtype->sarrayOf (s->cases->dim);
814 	vec<constructor_elt, va_gc> *elms = NULL;
815 
816 	s->cases->sort ();
817 
818 	for (size_t i = 0; i < s->cases->dim; i++)
819 	  {
820 	    CaseStatement *cs = (*s->cases)[i];
821 	    cs->index = i;
822 
823 	    if (cs->exp->op != TOKstring)
824 	      s->error ("case '%s' is not a string", cs->exp->toChars ());
825 	    else
826 	      {
827 		tree exp = build_expr (cs->exp, true);
828 		CONSTRUCTOR_APPEND_ELT (elms, size_int (i), exp);
829 	      }
830 	  }
831 
832 	/* Build static declaration to reference constructor.  */
833 	tree ctor = build_constructor (build_ctype (satype), elms);
834 	tree decl = build_artificial_decl (TREE_TYPE (ctor), ctor);
835 	TREE_READONLY (decl) = 1;
836 	d_pushdecl (decl);
837 	rest_of_decl_compilation (decl, 1, 0);
838 
839 	/* Pass it as a dynamic array.  */
840 	decl = d_array_value (build_ctype (condtype->arrayOf ()),
841 			      size_int (s->cases->dim),
842 			      build_address (decl));
843 
844 	condition = build_libcall (libcall, Type::tint32, 2, decl, condition);
845       }
846     else if (!condtype->isscalar ())
847       {
848 	error ("cannot handle switch condition of type %s",
849 	       condtype->toChars ());
850 	gcc_unreachable ();
851       }
852 
853     condition = fold (condition);
854 
855     /* Build LABEL_DECLs now so they can be refered to by goto case.
856        Also checking the jump from the switch to the label is allowed.  */
857     if (s->cases)
858       {
859 	for (size_t i = 0; i < s->cases->dim; i++)
860 	  {
861 	    CaseStatement *cs = (*s->cases)[i];
862 	    tree caselabel = this->lookup_label (cs);
863 
864 	    /* Write cases as a series of if-then-else blocks.
865 	       if (condition == case)
866 		 goto caselabel;  */
867 	    if (s->hasVars)
868 	      {
869 		tree ifcase = build2 (EQ_EXPR, build_ctype (condtype),
870 				      condition, build_expr_dtor (cs->exp));
871 		tree ifbody = fold_build1 (GOTO_EXPR, void_type_node,
872 					   caselabel);
873 		tree cond = build_vcondition (ifcase, ifbody, void_node);
874 		TREE_USED (caselabel) = 1;
875 		LABEL_VARIABLE_CASE (caselabel) = 1;
876 		add_stmt (cond);
877 	      }
878 
879 	    this->check_goto (s, cs);
880 	  }
881 
882 	if (s->sdefault)
883 	  {
884 	    tree defaultlabel = this->lookup_label (s->sdefault);
885 
886 	    /* The default label is the last 'else' block.  */
887 	    if (s->hasVars)
888 	      {
889 		this->do_jump (defaultlabel);
890 		LABEL_VARIABLE_CASE (defaultlabel) = 1;
891 	      }
892 
893 	    this->check_goto (s, s->sdefault);
894 	  }
895       }
896 
897     /* Switch body goes in its own statement list.  */
898     push_stmt_list ();
899     if (s->_body)
900       this->build_stmt (s->_body);
901 
902     tree casebody = pop_stmt_list ();
903 
904     /* Wrap up constructed body into a switch_expr, unless it was
905        converted to an if-then-else expression.  */
906     if (s->hasVars)
907       add_stmt (casebody);
908     else
909       {
910 	tree switchexpr = build2 (SWITCH_EXPR, TREE_TYPE (condition),
911 				  condition, casebody);
912 	add_stmt (switchexpr);
913 	SWITCH_ALL_CASES_P (switchexpr) = 1;
914       }
915 
916     SWITCH_BREAK_LABEL_P (lbreak) = 1;
917 
918     /* If the switch had any 'break' statements, emit the label now.  */
919     this->pop_break_label (lbreak);
920     this->finish_scope ();
921   }
922 
923   /* Declare the case label associated with the current SwitchStatement.  */
924 
visit(CaseStatement * s)925   void visit (CaseStatement *s)
926   {
927     /* Emit the case label.  */
928     tree label = this->define_label (s);
929 
930     if (LABEL_VARIABLE_CASE (label))
931       this->do_label (label);
932     else
933       {
934 	tree casevalue;
935 	if (s->exp->type->isscalar ())
936 	  casevalue = build_expr (s->exp);
937 	else
938 	  casevalue = build_integer_cst (s->index, build_ctype (Type::tint32));
939 
940 	tree caselabel = build_case_label (casevalue, NULL_TREE, label);
941 	add_stmt (caselabel);
942       }
943 
944     /* Now do the body.  */
945     if (s->statement)
946       this->build_stmt (s->statement);
947   }
948 
949   /* Declare the default label associated with the current SwitchStatement.  */
950 
visit(DefaultStatement * s)951   void visit (DefaultStatement *s)
952   {
953     /* Emit the default case label.  */
954     tree label = this->define_label (s);
955 
956     if (LABEL_VARIABLE_CASE (label))
957       this->do_label (label);
958     else
959       {
960 	tree caselabel = build_case_label (NULL_TREE, NULL_TREE, label);
961 	add_stmt (caselabel);
962       }
963 
964     /* Now do the body.  */
965     if (s->statement)
966       this->build_stmt (s->statement);
967   }
968 
969   /* Implements 'goto default' by jumping to the label associated with
970      the DefaultStatement in a switch block.  */
971 
visit(GotoDefaultStatement * s)972   void visit (GotoDefaultStatement *s)
973   {
974     tree label = this->lookup_label (s->sw->sdefault);
975     this->do_jump (label);
976   }
977 
978   /* Implements 'goto case' by jumping to the label associated with the
979      CaseStatement in a switch block.  */
980 
visit(GotoCaseStatement * s)981   void visit (GotoCaseStatement *s)
982   {
983     tree label = this->lookup_label (s->cs);
984     this->do_jump (label);
985   }
986 
987   /* Throw a SwitchError exception, called when a switch statement has
988      no DefaultStatement, yet none of the cases match.  */
989 
visit(SwitchErrorStatement * s)990   void visit (SwitchErrorStatement *s)
991   {
992     add_stmt (d_assert_call (s->loc, LIBCALL_SWITCH_ERROR));
993   }
994 
995   /* A return statement exits the current function and supplies its return
996      value, if the return type is not void.  */
997 
visit(ReturnStatement * s)998   void visit (ReturnStatement *s)
999   {
1000     if (s->exp == NULL || s->exp->type->toBasetype ()->ty == Tvoid)
1001       {
1002 	/* Return has no value.  */
1003 	add_stmt (return_expr (NULL_TREE));
1004 	return;
1005       }
1006 
1007     TypeFunction *tf = (TypeFunction *)this->func_->type;
1008     Type *type = this->func_->tintro != NULL
1009       ? this->func_->tintro->nextOf () : tf->nextOf ();
1010 
1011     if ((this->func_->isMain () || this->func_->isCMain ())
1012 	&& type->toBasetype ()->ty == Tvoid)
1013       type = Type::tint32;
1014 
1015     if (this->func_->nrvo_can && this->func_->nrvo_var)
1016       {
1017 	/* Just refer to the DECL_RESULT; this differs from using
1018 	   NULL_TREE in that it indicates that we care about the value
1019 	   of the DECL_RESULT.  */
1020 	tree decl = DECL_RESULT (get_symbol_decl (this->func_));
1021 	add_stmt (return_expr (decl));
1022       }
1023     else
1024       {
1025 	/* Convert for initializing the DECL_RESULT.  */
1026 	tree expr = build_return_dtor (s->exp, type, tf);
1027 	add_stmt (expr);
1028       }
1029   }
1030 
1031   /* Evaluate the enclosed expression, and add it to the statement list.  */
1032 
visit(ExpStatement * s)1033   void visit (ExpStatement *s)
1034   {
1035     if (s->exp)
1036       {
1037 	/* Expression may produce temporaries requiring scope destruction.  */
1038 	tree exp = build_expr_dtor (s->exp);
1039 	add_stmt (exp);
1040       }
1041   }
1042 
1043   /* Evaluate all enclosed statements.  */
1044 
visit(CompoundStatement * s)1045   void visit (CompoundStatement *s)
1046   {
1047     if (s->statements == NULL)
1048       return;
1049 
1050     for (size_t i = 0; i < s->statements->dim; i++)
1051       {
1052 	Statement *statement = (*s->statements)[i];
1053 
1054 	if (statement != NULL)
1055 	  this->build_stmt (statement);
1056       }
1057   }
1058 
1059   /* The frontend lowers `foreach (Tuple!(...))' statements as an unrolled loop.
1060      These are compiled down as a `do ... while (0)', where each unrolled loop
1061      is nested inside and given their own continue label to jump to.  */
1062 
visit(UnrolledLoopStatement * s)1063   void visit (UnrolledLoopStatement *s)
1064   {
1065     if (s->statements == NULL)
1066       return;
1067 
1068     tree lbreak = this->push_break_label (s);
1069     this->start_scope (level_loop);
1070 
1071     for (size_t i = 0; i < s->statements->dim; i++)
1072       {
1073 	Statement *statement = (*s->statements)[i];
1074 
1075 	if (statement != NULL)
1076 	  {
1077 	    tree lcontinue = this->push_continue_label (statement);
1078 	    this->build_stmt (statement);
1079 	    this->pop_continue_label (lcontinue);
1080 	  }
1081       }
1082 
1083     this->do_jump (this->break_label_);
1084 
1085     tree body = this->end_scope ();
1086     add_stmt (build1 (LOOP_EXPR, void_type_node, body));
1087 
1088     this->pop_break_label (lbreak);
1089   }
1090 
1091   /* Start a new scope and visit all nested statements, wrapping
1092      them up into a BIND_EXPR at the end of the scope.  */
1093 
visit(ScopeStatement * s)1094   void visit (ScopeStatement *s)
1095   {
1096     if (s->statement == NULL)
1097       return;
1098 
1099     this->start_scope (level_block);
1100     this->build_stmt (s->statement);
1101     this->finish_scope ();
1102   }
1103 
1104   /* A with statement is a way to simplify repeated references to the same
1105      object, where the handle is either a class or struct instance.  */
1106 
visit(WithStatement * s)1107   void visit (WithStatement *s)
1108   {
1109     this->start_scope (level_with);
1110 
1111     if (s->wthis)
1112       {
1113 	/* Perform initialisation of the 'with' handle.  */
1114 	ExpInitializer *ie = s->wthis->_init->isExpInitializer ();
1115 	gcc_assert (ie != NULL);
1116 
1117 	declare_local_var (s->wthis);
1118 	tree init = build_expr_dtor (ie->exp);
1119 	add_stmt (init);
1120       }
1121 
1122     if (s->_body)
1123       this->build_stmt (s->_body);
1124 
1125     this->finish_scope ();
1126   }
1127 
1128   /* Implements 'throw Object'.  Frontend already checks that the object
1129      thrown is a class type, but does not check if it is derived from
1130      Object.  Foreign objects are not currently supported at run-time.  */
1131 
visit(ThrowStatement * s)1132   void visit (ThrowStatement *s)
1133   {
1134     ClassDeclaration *cd = s->exp->type->toBasetype ()->isClassHandle ();
1135     InterfaceDeclaration *id = cd->isInterfaceDeclaration ();
1136     tree arg = build_expr_dtor (s->exp);
1137 
1138     if (!global.params.useExceptions)
1139       {
1140 	static int warned = 0;
1141 	if (!warned)
1142 	  {
1143 	    error_at (make_location_t (s->loc), "exception handling disabled, "
1144 		      "use -fexceptions to enable");
1145 	    warned = 1;
1146 	  }
1147       }
1148 
1149     if (cd->isCPPclass () || (id != NULL && id->isCPPclass ()))
1150       error_at (make_location_t (s->loc), "cannot throw C++ classes");
1151     else if (cd->com || (id != NULL && id->com))
1152       error_at (make_location_t (s->loc), "cannot throw COM objects");
1153     else
1154       arg = build_nop (build_ctype (get_object_type ()), arg);
1155 
1156     add_stmt (build_libcall (LIBCALL_THROW, Type::tvoid, 1, arg));
1157   }
1158 
1159   /* Build a try-catch statement, one of the building blocks for exception
1160      handling generated by the frontend.  This is also used to implement
1161      `scope (failure)' statements.  */
1162 
visit(TryCatchStatement * s)1163   void visit (TryCatchStatement *s)
1164   {
1165     this->start_scope (level_try);
1166     if (s->_body)
1167       this->build_stmt (s->_body);
1168 
1169     tree trybody = this->end_scope ();
1170 
1171     /* Try handlers go in their own statement list.  */
1172     push_stmt_list ();
1173 
1174     if (s->catches)
1175       {
1176 	for (size_t i = 0; i < s->catches->dim; i++)
1177 	  {
1178 	    Catch *vcatch = (*s->catches)[i];
1179 
1180 	    this->start_scope (level_catch);
1181 
1182 	    tree ehptr = builtin_decl_explicit (BUILT_IN_EH_POINTER);
1183 	    tree catchtype = build_ctype (vcatch->type);
1184 	    tree object = NULL_TREE;
1185 
1186 	    ehptr = build_call_expr (ehptr, 1, integer_zero_node);
1187 
1188 	    /* Retrieve the internal exception object, which could be for a
1189 	       D or C++ catch handler.  This is different from the generic
1190 	       exception pointer returned from gcc runtime.  */
1191 	    Type *tcatch = vcatch->type->toBasetype ();
1192 	    ClassDeclaration *cd = tcatch->isClassHandle ();
1193 
1194 	    libcall_fn libcall = (cd->isCPPclass ()) ? LIBCALL_CXA_BEGIN_CATCH
1195 	      : LIBCALL_BEGIN_CATCH;
1196 	    object = build_libcall (libcall, vcatch->type, 1, ehptr);
1197 
1198 	    if (vcatch->var)
1199 	      {
1200 		tree var = get_symbol_decl (vcatch->var);
1201 		tree init = build_assign (INIT_EXPR, var, object);
1202 
1203 		declare_local_var (vcatch->var);
1204 		add_stmt (init);
1205 	      }
1206 	    else
1207 	      {
1208 		/* Still need to emit a call to __gdc_begin_catch() to
1209 		   remove the object from the uncaught exceptions list.  */
1210 		add_stmt (object);
1211 	      }
1212 
1213 	    if (vcatch->handler)
1214 	      this->build_stmt (vcatch->handler);
1215 
1216 	    tree catchbody = this->end_scope ();
1217 
1218 	    /* Need to wrap C++ handlers in a try/finally block to signal
1219 	       the end catch callback.  */
1220 	    if (cd->isCPPclass ())
1221 	      {
1222 		tree endcatch = build_libcall (LIBCALL_CXA_END_CATCH,
1223 					       Type::tvoid, 0);
1224 		catchbody = build2 (TRY_FINALLY_EXPR, void_type_node,
1225 				    catchbody, endcatch);
1226 	      }
1227 
1228 	    add_stmt (build2 (CATCH_EXPR, void_type_node,
1229 			      catchtype, catchbody));
1230 	  }
1231       }
1232 
1233     tree catches = pop_stmt_list ();
1234 
1235     /* Back-end expects all catches in a TRY_CATCH_EXPR to be enclosed in a
1236        statement list, however pop_stmt_list may optimize away the list
1237        if there is only a single catch to push.  */
1238     if (TREE_CODE (catches) != STATEMENT_LIST)
1239       {
1240 	tree stmt_list = alloc_stmt_list ();
1241 	append_to_statement_list_force (catches, &stmt_list);
1242 	catches = stmt_list;
1243       }
1244 
1245     add_stmt (build2 (TRY_CATCH_EXPR, void_type_node, trybody, catches));
1246   }
1247 
1248   /* Build a try-finally statement, one of the building blocks for exception
1249      handling generated by the frontend.  This is also used to implement
1250      `scope (exit)' statements.  */
1251 
visit(TryFinallyStatement * s)1252   void visit (TryFinallyStatement *s)
1253   {
1254     this->start_scope (level_try);
1255     if (s->_body)
1256       this->build_stmt (s->_body);
1257 
1258     tree trybody = this->end_scope ();
1259 
1260     this->start_scope (level_finally);
1261     if (s->finalbody)
1262       this->build_stmt (s->finalbody);
1263 
1264     tree finally = this->end_scope ();
1265 
1266     add_stmt (build2 (TRY_FINALLY_EXPR, void_type_node, trybody, finally));
1267   }
1268 
1269   /* The frontend lowers `synchronized (...)' statements as a call to
1270      monitor/critical enter and exit wrapped around try/finally.
1271      This visitor is not strictly required other than to enforce that
1272      these kinds of statements never reach here.  */
1273 
visit(SynchronizedStatement *)1274   void visit (SynchronizedStatement *)
1275   {
1276     gcc_unreachable ();
1277   }
1278 
1279   /* D Inline Assembler is not implemented, as it would require writing
1280      an assembly parser for each supported target.  Instead we leverage
1281      GCC extended assembler using the GccAsmStatement class.  */
1282 
visit(AsmStatement *)1283   void visit (AsmStatement *)
1284   {
1285     sorry ("D inline assembler statements are not supported in GDC.");
1286   }
1287 
1288   /* Build a GCC extended assembler expression, whose components are
1289      an INSN string, some OUTPUTS, some INPUTS, and some CLOBBERS.  */
1290 
visit(GccAsmStatement * s)1291   void visit (GccAsmStatement *s)
1292   {
1293     StringExp *insn = (StringExp *)s->insn;
1294     tree outputs = NULL_TREE;
1295     tree inputs = NULL_TREE;
1296     tree clobbers = NULL_TREE;
1297     tree labels = NULL_TREE;
1298 
1299     /* Collect all arguments, which may be input or output operands.  */
1300     if (s->args)
1301       {
1302 	for (size_t i = 0; i < s->args->dim; i++)
1303 	  {
1304 	    Identifier *name = (*s->names)[i];
1305 	    const char *sname = name ? name->toChars () : NULL;
1306 	    tree id = name ? build_string (strlen (sname), sname) : NULL_TREE;
1307 
1308 	    StringExp *constr = (StringExp *)(*s->constraints)[i];
1309 	    const char *cstring = (const char *)(constr->len
1310 						 ? constr->string : "");
1311 	    tree str = build_string (constr->len, cstring);
1312 
1313 	    Expression *earg = (*s->args)[i];
1314 	    tree val = build_expr (earg);
1315 
1316 	    if (i < s->outputargs)
1317 	      {
1318 		tree arg = build_tree_list (id, str);
1319 		outputs = chainon (outputs, build_tree_list (arg, val));
1320 	      }
1321 	    else
1322 	      {
1323 		tree arg = build_tree_list (id, str);
1324 		inputs = chainon (inputs, build_tree_list (arg, val));
1325 	      }
1326 	  }
1327       }
1328 
1329     /* Collect all clobber arguments.  */
1330     if (s->clobbers)
1331       {
1332 	for (size_t i = 0; i < s->clobbers->dim; i++)
1333 	  {
1334 	    StringExp *clobber = (StringExp *)(*s->clobbers)[i];
1335 	    const char *cstring = (const char *)(clobber->len
1336 						 ? clobber->string : "");
1337 
1338 	    tree val = build_string (clobber->len, cstring);
1339 	    clobbers = chainon (clobbers, build_tree_list (0, val));
1340 	  }
1341       }
1342 
1343     /* Collect all goto labels, these should have been already checked
1344        by the front-end, so pass down the label symbol to the back-end.  */
1345     if (s->labels)
1346       {
1347 	for (size_t i = 0; i < s->labels->dim; i++)
1348 	  {
1349 	    Identifier *ident = (*s->labels)[i];
1350 	    GotoStatement *gs = (*s->gotos)[i];
1351 
1352 	    gcc_assert (gs->label->statement != NULL);
1353 	    gcc_assert (gs->tf == gs->label->statement->tf);
1354 
1355 	    const char *sident = ident->toChars ();
1356 	    tree name = build_string (strlen (sident), sident);
1357 	    tree label = this->lookup_label (gs->label->statement,
1358 					     gs->label->ident);
1359 	    TREE_USED (label) = 1;
1360 
1361 	    labels = chainon (labels, build_tree_list (name, label));
1362 	  }
1363       }
1364 
1365     /* Do some extra validation on all input and output operands.  */
1366     const char *insnstring = (const char *)(insn->len ? insn->string : "");
1367     tree string = build_string (insn->len, insnstring);
1368     string = resolve_asm_operand_names (string, outputs, inputs, labels);
1369 
1370     if (s->args)
1371       {
1372 	unsigned noutputs = s->outputargs;
1373 	unsigned ninputs = (s->args->dim - noutputs);
1374 	const char **oconstraints = XALLOCAVEC (const char *, noutputs);
1375 	bool allows_mem, allows_reg, is_inout;
1376 	size_t i;
1377 	tree t;
1378 
1379 	for (i = 0, t = outputs; t != NULL_TREE; t = TREE_CHAIN (t), i++)
1380 	  {
1381 	    tree output = TREE_VALUE (t);
1382 	    const char *constraint
1383 	      = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
1384 
1385 	    oconstraints[i] = constraint;
1386 
1387 	    if (parse_output_constraint (&constraint, i, ninputs, noutputs,
1388 					 &allows_mem, &allows_reg, &is_inout))
1389 	      {
1390 		/* If the output argument is going to end up in memory.  */
1391 		if (!allows_reg)
1392 		  d_mark_addressable (output);
1393 	      }
1394 	    else
1395 	      output = error_mark_node;
1396 
1397 	    TREE_VALUE (t) = output;
1398 	  }
1399 
1400 	for (i = 0, t = inputs; t != NULL_TREE; t = TREE_CHAIN (t), i++)
1401 	  {
1402 	    tree input = TREE_VALUE (t);
1403 	    const char *constraint
1404 	      = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
1405 
1406 	    if (parse_input_constraint (&constraint, i, ninputs, noutputs, 0,
1407 					oconstraints, &allows_mem, &allows_reg))
1408 	      {
1409 		/* If the input argument is going to end up in memory.  */
1410 		if (!allows_reg && allows_mem)
1411 		  d_mark_addressable (input);
1412 	      }
1413 	    else
1414 	      input = error_mark_node;
1415 
1416 	    TREE_VALUE (t) = input;
1417 	  }
1418       }
1419 
1420     tree exp = build5 (ASM_EXPR, void_type_node, string,
1421 		       outputs, inputs, clobbers, labels);
1422     SET_EXPR_LOCATION (exp, make_location_t (s->loc));
1423 
1424     /* If the extended syntax was not used, mark the ASM_EXPR.  */
1425     if (s->args == NULL && s->clobbers == NULL)
1426       ASM_INPUT_P (exp) = 1;
1427 
1428     /* Asm statements are treated as volatile unless 'pure'.  */
1429     ASM_VOLATILE_P (exp) = !(s->stc & STCpure);
1430 
1431     add_stmt (exp);
1432   }
1433 
1434   /* Import symbols from another module.  */
1435 
visit(ImportStatement * s)1436   void visit (ImportStatement *s)
1437   {
1438     if (s->imports == NULL)
1439       return;
1440 
1441     for (size_t i = 0; i < s->imports->dim; i++)
1442       {
1443 	Dsymbol *dsym = (*s->imports)[i];
1444 
1445 	if (dsym != NULL)
1446 	  build_decl_tree (dsym);
1447       }
1448   }
1449 };
1450 
1451 /* Main entry point for the IRVisitor interface to generate
1452    code for the body of function FD.  */
1453 
1454 void
build_function_body(FuncDeclaration * fd)1455 build_function_body (FuncDeclaration *fd)
1456 {
1457   IRVisitor v = IRVisitor (fd);
1458   location_t saved_location = input_location;
1459   input_location = make_location_t (fd->loc);
1460   v.build_stmt (fd->fbody);
1461   input_location = saved_location;
1462 }
1463