Line data Source code
1 : /* This file contains subroutine used by the C front-end to construct GENERIC.
2 : Copyright (C) 2000-2026 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 872533423 : push_stmt_list (void)
31 : {
32 872533423 : tree t;
33 872533423 : t = alloc_stmt_list ();
34 872533423 : vec_safe_push (stmt_list_stack, t);
35 872533423 : return t;
36 : }
37 :
38 : /* Return TRUE if, after I, there are any nondebug stmts. */
39 :
40 : static inline bool
41 212038463 : only_debug_stmts_after_p (tree_stmt_iterator i)
42 : {
43 273728654 : for (tsi_next (&i); !tsi_end_p (i); tsi_next (&i))
44 126414076 : 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 866397605 : pop_stmt_list (tree t)
53 : {
54 866397605 : 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 872532357 : while (1)
59 : {
60 872532357 : u = stmt_list_stack->pop ();
61 872532357 : if (!stmt_list_stack->is_empty ())
62 : {
63 669636998 : tree x = stmt_list_stack->last ();
64 669636998 : STATEMENT_LIST_HAS_LABEL (x) |= STATEMENT_LIST_HAS_LABEL (u);
65 : }
66 872532357 : if (t == u)
67 : break;
68 : }
69 :
70 866397605 : 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 866397605 : if (TREE_SIDE_EFFECTS (t))
78 : {
79 773705525 : tree_stmt_iterator i = tsi_start (t);
80 :
81 : /* If the statement list contained exactly one statement, then
82 : extract it immediately. */
83 773705525 : if (tsi_one_before_end_p (i))
84 : {
85 516700320 : u = tsi_stmt (i);
86 516700320 : tsi_delink (&i);
87 516700320 : free_stmt_list (t);
88 516700320 : 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 257005205 : else if (!tsi_end_p (i)
94 257005205 : && TREE_CODE (tsi_stmt (i)) == DEBUG_BEGIN_STMT)
95 : {
96 212038604 : u = tsi_stmt (i);
97 212038604 : tsi_next (&i);
98 424077208 : if (tsi_one_before_end_p (i)
99 145584040 : && 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 215903669 : while (!tsi_end_p (i)
111 215903669 : && TREE_CODE (tsi_stmt (i)) == DEBUG_BEGIN_STMT)
112 3865065 : 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 212038604 : if (tsi_end_p (i))
120 141 : TREE_SIDE_EFFECTS (t) = 0;
121 424076926 : else if (only_debug_stmts_after_p (i))
122 147314578 : TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (tsi_stmt (i));
123 : }
124 : }
125 :
126 866397605 : 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 608469900 : build_stmt (location_t loc, enum tree_code code, ...)
137 : {
138 608469900 : tree ret;
139 608469900 : int length, i;
140 608469900 : va_list p;
141 608469900 : bool side_effects;
142 :
143 : /* This function cannot be used to construct variably-sized nodes. */
144 608469900 : gcc_assert (TREE_CODE_CLASS (code) != tcc_vl_exp);
145 :
146 608469900 : va_start (p, code);
147 :
148 608469900 : ret = make_node (code);
149 608469900 : TREE_TYPE (ret) = void_type_node;
150 608469900 : length = TREE_CODE_LENGTH (code);
151 608469900 : 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 608469900 : side_effects = false;
159 1594699219 : for (i = 0; i < length; i++)
160 : {
161 986229319 : tree t = va_arg (p, tree);
162 986229319 : if (t && !TYPE_P (t))
163 556069427 : side_effects |= TREE_SIDE_EFFECTS (t);
164 986229319 : TREE_OPERAND (ret, i) = t;
165 : }
166 :
167 608469900 : TREE_SIDE_EFFECTS (ret) |= side_effects;
168 :
169 608469900 : va_end (p);
170 608469900 : return ret;
171 : }
172 :
173 : /* Build a REALPART_EXPR or IMAGPART_EXPR, according to CODE, from ARG. */
174 :
175 : tree
176 641632 : build_real_imag_expr (location_t location, enum tree_code code, tree arg)
177 : {
178 641632 : tree ret;
179 641632 : tree arg_type = TREE_TYPE (arg);
180 :
181 641632 : gcc_assert (code == REALPART_EXPR || code == IMAGPART_EXPR);
182 :
183 641632 : if (TREE_CODE (arg_type) == COMPLEX_TYPE)
184 : {
185 633849 : ret = build1 (code, TREE_TYPE (TREE_TYPE (arg)), arg);
186 633849 : 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 641632 : return ret;
203 : }
|