Branch data Line data Source code
1 : : /* This file contains subroutine used by the C front-end to construct GENERIC.
2 : : Copyright (C) 2000-2024 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 : 650857144 : push_stmt_list (void)
31 : : {
32 : 650857144 : tree t;
33 : 650857144 : t = alloc_stmt_list ();
34 : 650857144 : vec_safe_push (stmt_list_stack, t);
35 : 650857144 : return t;
36 : : }
37 : :
38 : : /* Return TRUE if, after I, there are any nondebug stmts. */
39 : :
40 : : static inline bool
41 : 171624651 : only_debug_stmts_after_p (tree_stmt_iterator i)
42 : : {
43 : 221555433 : for (tsi_next (&i); !tsi_end_p (i); tsi_next (&i))
44 : 101156583 : 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 : 645845987 : pop_stmt_list (tree t)
53 : : {
54 : 645845987 : 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 : 650856434 : while (1)
59 : : {
60 : 650856434 : u = stmt_list_stack->pop ();
61 : 650856434 : if (!stmt_list_stack->is_empty ())
62 : : {
63 : 481289475 : tree x = stmt_list_stack->last ();
64 : 481289475 : STATEMENT_LIST_HAS_LABEL (x) |= STATEMENT_LIST_HAS_LABEL (u);
65 : : }
66 : 650856434 : if (t == u)
67 : : break;
68 : : }
69 : :
70 : 645845987 : 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 : 645845987 : if (TREE_SIDE_EFFECTS (t))
78 : : {
79 : 577458968 : tree_stmt_iterator i = tsi_start (t);
80 : :
81 : : /* If the statement list contained exactly one statement, then
82 : : extract it immediately. */
83 : 577458968 : if (tsi_one_before_end_p (i))
84 : : {
85 : 371793354 : u = tsi_stmt (i);
86 : 371793354 : tsi_delink (&i);
87 : 371793354 : free_stmt_list (t);
88 : 371793354 : 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 : 205665614 : else if (!tsi_end_p (i)
94 : 205665614 : && TREE_CODE (tsi_stmt (i)) == DEBUG_BEGIN_STMT)
95 : : {
96 : 171624801 : u = tsi_stmt (i);
97 : 171624801 : tsi_next (&i);
98 : 343249602 : if (tsi_one_before_end_p (i)
99 : 118772567 : && TREE_CODE (tsi_stmt (i)) == STATEMENT_LIST)
100 : : {
101 : 0 : tree l = tsi_stmt (i);
102 : 0 : tsi_prev (&i);
103 : 0 : tsi_delink (&i);
104 : 0 : tsi_delink (&i);
105 : 0 : i = tsi_start (l);
106 : 0 : free_stmt_list (t);
107 : 0 : t = l;
108 : 0 : tsi_link_before (&i, u, TSI_SAME_STMT);
109 : : }
110 : 175221734 : while (!tsi_end_p (i)
111 : 175221734 : && TREE_CODE (tsi_stmt (i)) == DEBUG_BEGIN_STMT)
112 : 3596933 : 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 : 171624801 : if (tsi_end_p (i))
120 : 150 : TREE_SIDE_EFFECTS (t) = 0;
121 : 343249302 : else if (only_debug_stmts_after_p (i))
122 : 120398850 : TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (tsi_stmt (i));
123 : : }
124 : : }
125 : :
126 : 645845987 : 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 : 449508866 : build_stmt (location_t loc, enum tree_code code, ...)
137 : : {
138 : 449508866 : tree ret;
139 : 449508866 : int length, i;
140 : 449508866 : va_list p;
141 : 449508866 : bool side_effects;
142 : :
143 : : /* This function cannot be used to construct variably-sized nodes. */
144 : 449508866 : gcc_assert (TREE_CODE_CLASS (code) != tcc_vl_exp);
145 : :
146 : 449508866 : va_start (p, code);
147 : :
148 : 449508866 : ret = make_node (code);
149 : 449508866 : TREE_TYPE (ret) = void_type_node;
150 : 449508866 : length = TREE_CODE_LENGTH (code);
151 : 449508866 : 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 : 449508866 : side_effects = false;
159 : 1134831005 : for (i = 0; i < length; i++)
160 : : {
161 : 685322139 : tree t = va_arg (p, tree);
162 : 685322139 : if (t && !TYPE_P (t))
163 : 411741234 : side_effects |= TREE_SIDE_EFFECTS (t);
164 : 685322139 : TREE_OPERAND (ret, i) = t;
165 : : }
166 : :
167 : 449508866 : TREE_SIDE_EFFECTS (ret) |= side_effects;
168 : :
169 : 449508866 : va_end (p);
170 : 449508866 : return ret;
171 : : }
172 : :
173 : : /* Build a REALPART_EXPR or IMAGPART_EXPR, according to CODE, from ARG. */
174 : :
175 : : tree
176 : 655015 : build_real_imag_expr (location_t location, enum tree_code code, tree arg)
177 : : {
178 : 655015 : tree ret;
179 : 655015 : tree arg_type = TREE_TYPE (arg);
180 : :
181 : 655015 : gcc_assert (code == REALPART_EXPR || code == IMAGPART_EXPR);
182 : :
183 : 655015 : if (TREE_CODE (arg_type) == COMPLEX_TYPE)
184 : : {
185 : 647232 : ret = build1 (code, TREE_TYPE (TREE_TYPE (arg)), arg);
186 : 647232 : SET_EXPR_LOCATION (ret, location);
187 : : }
188 : 7783 : else if (INTEGRAL_TYPE_P (arg_type) || SCALAR_FLOAT_TYPE_P (arg_type))
189 : : {
190 : 7769 : ret = (code == REALPART_EXPR
191 : 7769 : ? arg
192 : 3872 : : omit_one_operand_loc (location, arg_type,
193 : : integer_zero_node, arg));
194 : : }
195 : : else
196 : : {
197 : 21 : error_at (location, "wrong type argument to %s",
198 : : code == REALPART_EXPR ? "__real" : "__imag");
199 : 14 : ret = error_mark_node;
200 : : }
201 : :
202 : 655015 : return ret;
203 : : }
|