1 /* This file contains subroutine used by the C front-end to construct GENERIC.
2    Copyright (C) 2000-2018 Free Software Foundation, Inc.
3    Written by Benjamin Chelf (chelf@codesourcery.com).
4 
5 This file is part of GCC.
6 
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
11 
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3.  If not see
19 <http://www.gnu.org/licenses/>.  */
20 
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "c-common.h"
25 #include "tree-iterator.h"
26 
27 /* Create an empty statement tree rooted at T.  */
28 
29 tree
30 push_stmt_list (void)
31 {
32   tree t;
33   t = alloc_stmt_list ();
34   vec_safe_push (stmt_list_stack, t);
35   return t;
36 }
37 
38 /* Return TRUE if, after I, there are any nondebug stmts.  */
39 
40 static inline bool
41 only_debug_stmts_after_p (tree_stmt_iterator i)
42 {
43   for (tsi_next (&i); !tsi_end_p (i); tsi_next (&i))
44     if (TREE_CODE (tsi_stmt (i)) != DEBUG_BEGIN_STMT)
45       return false;
46   return true;
47 }
48 
49 /* Finish the statement tree rooted at T.  */
50 
51 tree
52 pop_stmt_list (tree t)
53 {
54   tree u = NULL_TREE;
55 
56   /* Pop statement lists until we reach the target level.  The extra
57      nestings will be due to outstanding cleanups.  */
58   while (1)
59     {
60       u = stmt_list_stack->pop ();
61       if (!stmt_list_stack->is_empty ())
62 	{
63 	  tree x = stmt_list_stack->last ();
64 	  STATEMENT_LIST_HAS_LABEL (x) |= STATEMENT_LIST_HAS_LABEL (u);
65 	}
66       if (t == u)
67 	break;
68     }
69 
70   gcc_assert (u != NULL_TREE);
71 
72   /* If the statement list is completely empty, just return it.  This is
73      just as good small as build_empty_stmt, with the advantage that
74      statement lists are merged when they appended to one another.  So
75      using the STATEMENT_LIST avoids pathological buildup of EMPTY_STMT_P
76      statements.  */
77   if (TREE_SIDE_EFFECTS (t))
78     {
79       tree_stmt_iterator i = tsi_start (t);
80 
81       /* If the statement list contained exactly one statement, then
82 	 extract it immediately.  */
83       if (tsi_one_before_end_p (i))
84 	{
85 	  u = tsi_stmt (i);
86 	  tsi_delink (&i);
87 	  free_stmt_list (t);
88 	  t = u;
89 	}
90       /* If the statement list contained a debug begin stmt and a
91 	 statement list, move the debug begin stmt into the statement
92 	 list and return it.  */
93       else if (!tsi_end_p (i)
94 	       && TREE_CODE (tsi_stmt (i)) == DEBUG_BEGIN_STMT)
95 	{
96 	  u = tsi_stmt (i);
97 	  tsi_next (&i);
98 	  if (tsi_one_before_end_p (i)
99 	      && TREE_CODE (tsi_stmt (i)) == STATEMENT_LIST)
100 	    {
101 	      tree l = tsi_stmt (i);
102 	      tsi_prev (&i);
103 	      tsi_delink (&i);
104 	      tsi_delink (&i);
105 	      i = tsi_start (l);
106 	      free_stmt_list (t);
107 	      t = l;
108 	      tsi_link_before (&i, u, TSI_SAME_STMT);
109 	    }
110 	  while (!tsi_end_p (i)
111 		 && TREE_CODE (tsi_stmt (i)) == DEBUG_BEGIN_STMT)
112 	    tsi_next (&i);
113 	  /* If there are only debug stmts in the list, without them
114 	     we'd have an empty stmt without side effects.  If there's
115 	     only one nondebug stmt, we'd have extracted the stmt and
116 	     dropped the list, and we'd take TREE_SIDE_EFFECTS from
117 	     that statement.  In either case, keep the list's
118 	     TREE_SIDE_EFFECTS in sync.  */
119 	  if (tsi_end_p (i))
120 	    TREE_SIDE_EFFECTS (t) = 0;
121 	  else if (only_debug_stmts_after_p (i))
122 	    TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (tsi_stmt (i));
123 	}
124     }
125 
126   return t;
127 }
128 
129 /* Build a generic statement based on the given type of node and
130    arguments. Similar to `build_nt', except that we set
131    EXPR_LOCATION to LOC. */
132 /* ??? This should be obsolete with the lineno_stmt productions
133    in the grammar.  */
134 
135 tree
136 build_stmt (location_t loc, enum tree_code code, ...)
137 {
138   tree ret;
139   int length, i;
140   va_list p;
141   bool side_effects;
142 
143   /* This function cannot be used to construct variably-sized nodes.  */
144   gcc_assert (TREE_CODE_CLASS (code) != tcc_vl_exp);
145 
146   va_start (p, code);
147 
148   ret = make_node (code);
149   TREE_TYPE (ret) = void_type_node;
150   length = TREE_CODE_LENGTH (code);
151   SET_EXPR_LOCATION (ret, loc);
152 
153   /* TREE_SIDE_EFFECTS will already be set for statements with
154      implicit side effects.  Here we make sure it is set for other
155      expressions by checking whether the parameters have side
156      effects.  */
157 
158   side_effects = false;
159   for (i = 0; i < length; i++)
160     {
161       tree t = va_arg (p, tree);
162       if (t && !TYPE_P (t))
163 	side_effects |= TREE_SIDE_EFFECTS (t);
164       TREE_OPERAND (ret, i) = t;
165     }
166 
167   TREE_SIDE_EFFECTS (ret) |= side_effects;
168 
169   va_end (p);
170   return ret;
171 }
172 
173 /* Build a REALPART_EXPR or IMAGPART_EXPR, according to CODE, from ARG.  */
174 
175 tree
176 build_real_imag_expr (location_t location, enum tree_code code, tree arg)
177 {
178   tree ret;
179   tree arg_type = TREE_TYPE (arg);
180 
181   gcc_assert (code == REALPART_EXPR || code == IMAGPART_EXPR);
182 
183   if (TREE_CODE (arg_type) == COMPLEX_TYPE)
184     {
185       ret = build1 (code, TREE_TYPE (TREE_TYPE (arg)), arg);
186       SET_EXPR_LOCATION (ret, location);
187     }
188   else if (INTEGRAL_TYPE_P (arg_type) || SCALAR_FLOAT_TYPE_P (arg_type))
189     {
190       ret = (code == REALPART_EXPR
191 	     ? arg
192 	     : omit_one_operand_loc (location, arg_type,
193 				     integer_zero_node, arg));
194     }
195   else
196     {
197       error_at (location, "wrong type argument to %s",
198 		code == REALPART_EXPR ? "__real" : "__imag");
199       ret = error_mark_node;
200     }
201 
202   return ret;
203 }
204