annotate gcc/gimple-expr.c @ 131:84e7813d76e9

gcc-8.2
author mir3636
date Thu, 25 Oct 2018 07:37:49 +0900
parents 04ced10e8804
children 1830386684a0
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 /* Gimple decl, type, and expression support functions.
kono
parents:
diff changeset
2
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3 Copyright (C) 2007-2018 Free Software Foundation, Inc.
111
kono
parents:
diff changeset
4 Contributed by Aldy Hernandez <aldyh@redhat.com>
kono
parents:
diff changeset
5
kono
parents:
diff changeset
6 This file is part of GCC.
kono
parents:
diff changeset
7
kono
parents:
diff changeset
8 GCC is free software; you can redistribute it and/or modify it under
kono
parents:
diff changeset
9 the terms of the GNU General Public License as published by the Free
kono
parents:
diff changeset
10 Software Foundation; either version 3, or (at your option) any later
kono
parents:
diff changeset
11 version.
kono
parents:
diff changeset
12
kono
parents:
diff changeset
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
kono
parents:
diff changeset
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
kono
parents:
diff changeset
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
kono
parents:
diff changeset
16 for more details.
kono
parents:
diff changeset
17
kono
parents:
diff changeset
18 You should have received a copy of the GNU General Public License
kono
parents:
diff changeset
19 along with GCC; see the file COPYING3. If not see
kono
parents:
diff changeset
20 <http://www.gnu.org/licenses/>. */
kono
parents:
diff changeset
21
kono
parents:
diff changeset
22 #include "config.h"
kono
parents:
diff changeset
23 #include "system.h"
kono
parents:
diff changeset
24 #include "coretypes.h"
kono
parents:
diff changeset
25 #include "backend.h"
kono
parents:
diff changeset
26 #include "tree.h"
kono
parents:
diff changeset
27 #include "gimple.h"
kono
parents:
diff changeset
28 #include "stringpool.h"
kono
parents:
diff changeset
29 #include "gimple-ssa.h"
kono
parents:
diff changeset
30 #include "fold-const.h"
kono
parents:
diff changeset
31 #include "tree-eh.h"
kono
parents:
diff changeset
32 #include "gimplify.h"
kono
parents:
diff changeset
33 #include "stor-layout.h"
kono
parents:
diff changeset
34 #include "demangle.h"
kono
parents:
diff changeset
35 #include "hash-set.h"
kono
parents:
diff changeset
36 #include "rtl.h"
kono
parents:
diff changeset
37 #include "tree-pass.h"
kono
parents:
diff changeset
38 #include "stringpool.h"
kono
parents:
diff changeset
39 #include "attribs.h"
kono
parents:
diff changeset
40
kono
parents:
diff changeset
41 /* ----- Type related ----- */
kono
parents:
diff changeset
42
kono
parents:
diff changeset
43 /* Return true if the conversion from INNER_TYPE to OUTER_TYPE is a
kono
parents:
diff changeset
44 useless type conversion, otherwise return false.
kono
parents:
diff changeset
45
kono
parents:
diff changeset
46 This function implicitly defines the middle-end type system. With
kono
parents:
diff changeset
47 the notion of 'a < b' meaning that useless_type_conversion_p (a, b)
kono
parents:
diff changeset
48 holds and 'a > b' meaning that useless_type_conversion_p (b, a) holds,
kono
parents:
diff changeset
49 the following invariants shall be fulfilled:
kono
parents:
diff changeset
50
kono
parents:
diff changeset
51 1) useless_type_conversion_p is transitive.
kono
parents:
diff changeset
52 If a < b and b < c then a < c.
kono
parents:
diff changeset
53
kono
parents:
diff changeset
54 2) useless_type_conversion_p is not symmetric.
kono
parents:
diff changeset
55 From a < b does not follow a > b.
kono
parents:
diff changeset
56
kono
parents:
diff changeset
57 3) Types define the available set of operations applicable to values.
kono
parents:
diff changeset
58 A type conversion is useless if the operations for the target type
kono
parents:
diff changeset
59 is a subset of the operations for the source type. For example
kono
parents:
diff changeset
60 casts to void* are useless, casts from void* are not (void* can't
kono
parents:
diff changeset
61 be dereferenced or offsetted, but copied, hence its set of operations
kono
parents:
diff changeset
62 is a strict subset of that of all other data pointer types). Casts
kono
parents:
diff changeset
63 to const T* are useless (can't be written to), casts from const T*
kono
parents:
diff changeset
64 to T* are not. */
kono
parents:
diff changeset
65
kono
parents:
diff changeset
66 bool
kono
parents:
diff changeset
67 useless_type_conversion_p (tree outer_type, tree inner_type)
kono
parents:
diff changeset
68 {
kono
parents:
diff changeset
69 /* Do the following before stripping toplevel qualifiers. */
kono
parents:
diff changeset
70 if (POINTER_TYPE_P (inner_type)
kono
parents:
diff changeset
71 && POINTER_TYPE_P (outer_type))
kono
parents:
diff changeset
72 {
kono
parents:
diff changeset
73 /* Do not lose casts between pointers to different address spaces. */
kono
parents:
diff changeset
74 if (TYPE_ADDR_SPACE (TREE_TYPE (outer_type))
kono
parents:
diff changeset
75 != TYPE_ADDR_SPACE (TREE_TYPE (inner_type)))
kono
parents:
diff changeset
76 return false;
kono
parents:
diff changeset
77 /* Do not lose casts to function pointer types. */
kono
parents:
diff changeset
78 if ((TREE_CODE (TREE_TYPE (outer_type)) == FUNCTION_TYPE
kono
parents:
diff changeset
79 || TREE_CODE (TREE_TYPE (outer_type)) == METHOD_TYPE)
kono
parents:
diff changeset
80 && !(TREE_CODE (TREE_TYPE (inner_type)) == FUNCTION_TYPE
kono
parents:
diff changeset
81 || TREE_CODE (TREE_TYPE (inner_type)) == METHOD_TYPE))
kono
parents:
diff changeset
82 return false;
kono
parents:
diff changeset
83 }
kono
parents:
diff changeset
84
kono
parents:
diff changeset
85 /* From now on qualifiers on value types do not matter. */
kono
parents:
diff changeset
86 inner_type = TYPE_MAIN_VARIANT (inner_type);
kono
parents:
diff changeset
87 outer_type = TYPE_MAIN_VARIANT (outer_type);
kono
parents:
diff changeset
88
kono
parents:
diff changeset
89 if (inner_type == outer_type)
kono
parents:
diff changeset
90 return true;
kono
parents:
diff changeset
91
kono
parents:
diff changeset
92 /* Changes in machine mode are never useless conversions because the RTL
kono
parents:
diff changeset
93 middle-end expects explicit conversions between modes. */
kono
parents:
diff changeset
94 if (TYPE_MODE (inner_type) != TYPE_MODE (outer_type))
kono
parents:
diff changeset
95 return false;
kono
parents:
diff changeset
96
kono
parents:
diff changeset
97 /* If both the inner and outer types are integral types, then the
kono
parents:
diff changeset
98 conversion is not necessary if they have the same mode and
kono
parents:
diff changeset
99 signedness and precision, and both or neither are boolean. */
kono
parents:
diff changeset
100 if (INTEGRAL_TYPE_P (inner_type)
kono
parents:
diff changeset
101 && INTEGRAL_TYPE_P (outer_type))
kono
parents:
diff changeset
102 {
kono
parents:
diff changeset
103 /* Preserve changes in signedness or precision. */
kono
parents:
diff changeset
104 if (TYPE_UNSIGNED (inner_type) != TYPE_UNSIGNED (outer_type)
kono
parents:
diff changeset
105 || TYPE_PRECISION (inner_type) != TYPE_PRECISION (outer_type))
kono
parents:
diff changeset
106 return false;
kono
parents:
diff changeset
107
kono
parents:
diff changeset
108 /* Preserve conversions to/from BOOLEAN_TYPE if types are not
kono
parents:
diff changeset
109 of precision one. */
kono
parents:
diff changeset
110 if (((TREE_CODE (inner_type) == BOOLEAN_TYPE)
kono
parents:
diff changeset
111 != (TREE_CODE (outer_type) == BOOLEAN_TYPE))
kono
parents:
diff changeset
112 && TYPE_PRECISION (outer_type) != 1)
kono
parents:
diff changeset
113 return false;
kono
parents:
diff changeset
114
kono
parents:
diff changeset
115 /* We don't need to preserve changes in the types minimum or
kono
parents:
diff changeset
116 maximum value in general as these do not generate code
kono
parents:
diff changeset
117 unless the types precisions are different. */
kono
parents:
diff changeset
118 return true;
kono
parents:
diff changeset
119 }
kono
parents:
diff changeset
120
kono
parents:
diff changeset
121 /* Scalar floating point types with the same mode are compatible. */
kono
parents:
diff changeset
122 else if (SCALAR_FLOAT_TYPE_P (inner_type)
kono
parents:
diff changeset
123 && SCALAR_FLOAT_TYPE_P (outer_type))
kono
parents:
diff changeset
124 return true;
kono
parents:
diff changeset
125
kono
parents:
diff changeset
126 /* Fixed point types with the same mode are compatible. */
kono
parents:
diff changeset
127 else if (FIXED_POINT_TYPE_P (inner_type)
kono
parents:
diff changeset
128 && FIXED_POINT_TYPE_P (outer_type))
kono
parents:
diff changeset
129 return TYPE_SATURATING (inner_type) == TYPE_SATURATING (outer_type);
kono
parents:
diff changeset
130
kono
parents:
diff changeset
131 /* We need to take special care recursing to pointed-to types. */
kono
parents:
diff changeset
132 else if (POINTER_TYPE_P (inner_type)
kono
parents:
diff changeset
133 && POINTER_TYPE_P (outer_type))
kono
parents:
diff changeset
134 {
kono
parents:
diff changeset
135 /* We do not care for const qualification of the pointed-to types
kono
parents:
diff changeset
136 as const qualification has no semantic value to the middle-end. */
kono
parents:
diff changeset
137
kono
parents:
diff changeset
138 /* Otherwise pointers/references are equivalent. */
kono
parents:
diff changeset
139 return true;
kono
parents:
diff changeset
140 }
kono
parents:
diff changeset
141
kono
parents:
diff changeset
142 /* Recurse for complex types. */
kono
parents:
diff changeset
143 else if (TREE_CODE (inner_type) == COMPLEX_TYPE
kono
parents:
diff changeset
144 && TREE_CODE (outer_type) == COMPLEX_TYPE)
kono
parents:
diff changeset
145 return useless_type_conversion_p (TREE_TYPE (outer_type),
kono
parents:
diff changeset
146 TREE_TYPE (inner_type));
kono
parents:
diff changeset
147
kono
parents:
diff changeset
148 /* Recurse for vector types with the same number of subparts. */
kono
parents:
diff changeset
149 else if (TREE_CODE (inner_type) == VECTOR_TYPE
kono
parents:
diff changeset
150 && TREE_CODE (outer_type) == VECTOR_TYPE
kono
parents:
diff changeset
151 && TYPE_PRECISION (inner_type) == TYPE_PRECISION (outer_type))
kono
parents:
diff changeset
152 return useless_type_conversion_p (TREE_TYPE (outer_type),
kono
parents:
diff changeset
153 TREE_TYPE (inner_type));
kono
parents:
diff changeset
154
kono
parents:
diff changeset
155 else if (TREE_CODE (inner_type) == ARRAY_TYPE
kono
parents:
diff changeset
156 && TREE_CODE (outer_type) == ARRAY_TYPE)
kono
parents:
diff changeset
157 {
kono
parents:
diff changeset
158 /* Preserve various attributes. */
kono
parents:
diff changeset
159 if (TYPE_REVERSE_STORAGE_ORDER (inner_type)
kono
parents:
diff changeset
160 != TYPE_REVERSE_STORAGE_ORDER (outer_type))
kono
parents:
diff changeset
161 return false;
kono
parents:
diff changeset
162 if (TYPE_STRING_FLAG (inner_type) != TYPE_STRING_FLAG (outer_type))
kono
parents:
diff changeset
163 return false;
kono
parents:
diff changeset
164
kono
parents:
diff changeset
165 /* Conversions from array types with unknown extent to
kono
parents:
diff changeset
166 array types with known extent are not useless. */
kono
parents:
diff changeset
167 if (!TYPE_DOMAIN (inner_type) && TYPE_DOMAIN (outer_type))
kono
parents:
diff changeset
168 return false;
kono
parents:
diff changeset
169
kono
parents:
diff changeset
170 /* Nor are conversions from array types with non-constant size to
kono
parents:
diff changeset
171 array types with constant size or to different size. */
kono
parents:
diff changeset
172 if (TYPE_SIZE (outer_type)
kono
parents:
diff changeset
173 && TREE_CODE (TYPE_SIZE (outer_type)) == INTEGER_CST
kono
parents:
diff changeset
174 && (!TYPE_SIZE (inner_type)
kono
parents:
diff changeset
175 || TREE_CODE (TYPE_SIZE (inner_type)) != INTEGER_CST
kono
parents:
diff changeset
176 || !tree_int_cst_equal (TYPE_SIZE (outer_type),
kono
parents:
diff changeset
177 TYPE_SIZE (inner_type))))
kono
parents:
diff changeset
178 return false;
kono
parents:
diff changeset
179
kono
parents:
diff changeset
180 /* Check conversions between arrays with partially known extents.
kono
parents:
diff changeset
181 If the array min/max values are constant they have to match.
kono
parents:
diff changeset
182 Otherwise allow conversions to unknown and variable extents.
kono
parents:
diff changeset
183 In particular this declares conversions that may change the
kono
parents:
diff changeset
184 mode to BLKmode as useless. */
kono
parents:
diff changeset
185 if (TYPE_DOMAIN (inner_type)
kono
parents:
diff changeset
186 && TYPE_DOMAIN (outer_type)
kono
parents:
diff changeset
187 && TYPE_DOMAIN (inner_type) != TYPE_DOMAIN (outer_type))
kono
parents:
diff changeset
188 {
kono
parents:
diff changeset
189 tree inner_min = TYPE_MIN_VALUE (TYPE_DOMAIN (inner_type));
kono
parents:
diff changeset
190 tree outer_min = TYPE_MIN_VALUE (TYPE_DOMAIN (outer_type));
kono
parents:
diff changeset
191 tree inner_max = TYPE_MAX_VALUE (TYPE_DOMAIN (inner_type));
kono
parents:
diff changeset
192 tree outer_max = TYPE_MAX_VALUE (TYPE_DOMAIN (outer_type));
kono
parents:
diff changeset
193
kono
parents:
diff changeset
194 /* After gimplification a variable min/max value carries no
kono
parents:
diff changeset
195 additional information compared to a NULL value. All that
kono
parents:
diff changeset
196 matters has been lowered to be part of the IL. */
kono
parents:
diff changeset
197 if (inner_min && TREE_CODE (inner_min) != INTEGER_CST)
kono
parents:
diff changeset
198 inner_min = NULL_TREE;
kono
parents:
diff changeset
199 if (outer_min && TREE_CODE (outer_min) != INTEGER_CST)
kono
parents:
diff changeset
200 outer_min = NULL_TREE;
kono
parents:
diff changeset
201 if (inner_max && TREE_CODE (inner_max) != INTEGER_CST)
kono
parents:
diff changeset
202 inner_max = NULL_TREE;
kono
parents:
diff changeset
203 if (outer_max && TREE_CODE (outer_max) != INTEGER_CST)
kono
parents:
diff changeset
204 outer_max = NULL_TREE;
kono
parents:
diff changeset
205
kono
parents:
diff changeset
206 /* Conversions NULL / variable <- cst are useless, but not
kono
parents:
diff changeset
207 the other way around. */
kono
parents:
diff changeset
208 if (outer_min
kono
parents:
diff changeset
209 && (!inner_min
kono
parents:
diff changeset
210 || !tree_int_cst_equal (inner_min, outer_min)))
kono
parents:
diff changeset
211 return false;
kono
parents:
diff changeset
212 if (outer_max
kono
parents:
diff changeset
213 && (!inner_max
kono
parents:
diff changeset
214 || !tree_int_cst_equal (inner_max, outer_max)))
kono
parents:
diff changeset
215 return false;
kono
parents:
diff changeset
216 }
kono
parents:
diff changeset
217
kono
parents:
diff changeset
218 /* Recurse on the element check. */
kono
parents:
diff changeset
219 return useless_type_conversion_p (TREE_TYPE (outer_type),
kono
parents:
diff changeset
220 TREE_TYPE (inner_type));
kono
parents:
diff changeset
221 }
kono
parents:
diff changeset
222
kono
parents:
diff changeset
223 else if ((TREE_CODE (inner_type) == FUNCTION_TYPE
kono
parents:
diff changeset
224 || TREE_CODE (inner_type) == METHOD_TYPE)
kono
parents:
diff changeset
225 && TREE_CODE (inner_type) == TREE_CODE (outer_type))
kono
parents:
diff changeset
226 {
kono
parents:
diff changeset
227 tree outer_parm, inner_parm;
kono
parents:
diff changeset
228
kono
parents:
diff changeset
229 /* If the return types are not compatible bail out. */
kono
parents:
diff changeset
230 if (!useless_type_conversion_p (TREE_TYPE (outer_type),
kono
parents:
diff changeset
231 TREE_TYPE (inner_type)))
kono
parents:
diff changeset
232 return false;
kono
parents:
diff changeset
233
kono
parents:
diff changeset
234 /* Method types should belong to a compatible base class. */
kono
parents:
diff changeset
235 if (TREE_CODE (inner_type) == METHOD_TYPE
kono
parents:
diff changeset
236 && !useless_type_conversion_p (TYPE_METHOD_BASETYPE (outer_type),
kono
parents:
diff changeset
237 TYPE_METHOD_BASETYPE (inner_type)))
kono
parents:
diff changeset
238 return false;
kono
parents:
diff changeset
239
kono
parents:
diff changeset
240 /* A conversion to an unprototyped argument list is ok. */
kono
parents:
diff changeset
241 if (!prototype_p (outer_type))
kono
parents:
diff changeset
242 return true;
kono
parents:
diff changeset
243
kono
parents:
diff changeset
244 /* If the unqualified argument types are compatible the conversion
kono
parents:
diff changeset
245 is useless. */
kono
parents:
diff changeset
246 if (TYPE_ARG_TYPES (outer_type) == TYPE_ARG_TYPES (inner_type))
kono
parents:
diff changeset
247 return true;
kono
parents:
diff changeset
248
kono
parents:
diff changeset
249 for (outer_parm = TYPE_ARG_TYPES (outer_type),
kono
parents:
diff changeset
250 inner_parm = TYPE_ARG_TYPES (inner_type);
kono
parents:
diff changeset
251 outer_parm && inner_parm;
kono
parents:
diff changeset
252 outer_parm = TREE_CHAIN (outer_parm),
kono
parents:
diff changeset
253 inner_parm = TREE_CHAIN (inner_parm))
kono
parents:
diff changeset
254 if (!useless_type_conversion_p
kono
parents:
diff changeset
255 (TYPE_MAIN_VARIANT (TREE_VALUE (outer_parm)),
kono
parents:
diff changeset
256 TYPE_MAIN_VARIANT (TREE_VALUE (inner_parm))))
kono
parents:
diff changeset
257 return false;
kono
parents:
diff changeset
258
kono
parents:
diff changeset
259 /* If there is a mismatch in the number of arguments the functions
kono
parents:
diff changeset
260 are not compatible. */
kono
parents:
diff changeset
261 if (outer_parm || inner_parm)
kono
parents:
diff changeset
262 return false;
kono
parents:
diff changeset
263
kono
parents:
diff changeset
264 /* Defer to the target if necessary. */
kono
parents:
diff changeset
265 if (TYPE_ATTRIBUTES (inner_type) || TYPE_ATTRIBUTES (outer_type))
kono
parents:
diff changeset
266 return comp_type_attributes (outer_type, inner_type) != 0;
kono
parents:
diff changeset
267
kono
parents:
diff changeset
268 return true;
kono
parents:
diff changeset
269 }
kono
parents:
diff changeset
270
kono
parents:
diff changeset
271 /* For aggregates we rely on TYPE_CANONICAL exclusively and require
kono
parents:
diff changeset
272 explicit conversions for types involving to be structurally
kono
parents:
diff changeset
273 compared types. */
kono
parents:
diff changeset
274 else if (AGGREGATE_TYPE_P (inner_type)
kono
parents:
diff changeset
275 && TREE_CODE (inner_type) == TREE_CODE (outer_type))
kono
parents:
diff changeset
276 return TYPE_CANONICAL (inner_type)
kono
parents:
diff changeset
277 && TYPE_CANONICAL (inner_type) == TYPE_CANONICAL (outer_type);
kono
parents:
diff changeset
278
kono
parents:
diff changeset
279 else if (TREE_CODE (inner_type) == OFFSET_TYPE
kono
parents:
diff changeset
280 && TREE_CODE (outer_type) == OFFSET_TYPE)
kono
parents:
diff changeset
281 return useless_type_conversion_p (TREE_TYPE (outer_type),
kono
parents:
diff changeset
282 TREE_TYPE (inner_type))
kono
parents:
diff changeset
283 && useless_type_conversion_p
kono
parents:
diff changeset
284 (TYPE_OFFSET_BASETYPE (outer_type),
kono
parents:
diff changeset
285 TYPE_OFFSET_BASETYPE (inner_type));
kono
parents:
diff changeset
286
kono
parents:
diff changeset
287 return false;
kono
parents:
diff changeset
288 }
kono
parents:
diff changeset
289
kono
parents:
diff changeset
290
kono
parents:
diff changeset
291 /* ----- Decl related ----- */
kono
parents:
diff changeset
292
kono
parents:
diff changeset
293 /* Set sequence SEQ to be the GIMPLE body for function FN. */
kono
parents:
diff changeset
294
kono
parents:
diff changeset
295 void
kono
parents:
diff changeset
296 gimple_set_body (tree fndecl, gimple_seq seq)
kono
parents:
diff changeset
297 {
kono
parents:
diff changeset
298 struct function *fn = DECL_STRUCT_FUNCTION (fndecl);
kono
parents:
diff changeset
299 if (fn == NULL)
kono
parents:
diff changeset
300 {
kono
parents:
diff changeset
301 /* If FNDECL still does not have a function structure associated
kono
parents:
diff changeset
302 with it, then it does not make sense for it to receive a
kono
parents:
diff changeset
303 GIMPLE body. */
kono
parents:
diff changeset
304 gcc_assert (seq == NULL);
kono
parents:
diff changeset
305 }
kono
parents:
diff changeset
306 else
kono
parents:
diff changeset
307 fn->gimple_body = seq;
kono
parents:
diff changeset
308 }
kono
parents:
diff changeset
309
kono
parents:
diff changeset
310
kono
parents:
diff changeset
311 /* Return the body of GIMPLE statements for function FN. After the
kono
parents:
diff changeset
312 CFG pass, the function body doesn't exist anymore because it has
kono
parents:
diff changeset
313 been split up into basic blocks. In this case, it returns
kono
parents:
diff changeset
314 NULL. */
kono
parents:
diff changeset
315
kono
parents:
diff changeset
316 gimple_seq
kono
parents:
diff changeset
317 gimple_body (tree fndecl)
kono
parents:
diff changeset
318 {
kono
parents:
diff changeset
319 struct function *fn = DECL_STRUCT_FUNCTION (fndecl);
kono
parents:
diff changeset
320 return fn ? fn->gimple_body : NULL;
kono
parents:
diff changeset
321 }
kono
parents:
diff changeset
322
kono
parents:
diff changeset
323 /* Return true when FNDECL has Gimple body either in unlowered
kono
parents:
diff changeset
324 or CFG form. */
kono
parents:
diff changeset
325 bool
kono
parents:
diff changeset
326 gimple_has_body_p (tree fndecl)
kono
parents:
diff changeset
327 {
kono
parents:
diff changeset
328 struct function *fn = DECL_STRUCT_FUNCTION (fndecl);
kono
parents:
diff changeset
329 return (gimple_body (fndecl) || (fn && fn->cfg && !(fn->curr_properties & PROP_rtl)));
kono
parents:
diff changeset
330 }
kono
parents:
diff changeset
331
kono
parents:
diff changeset
332 /* Return a printable name for symbol DECL. */
kono
parents:
diff changeset
333
kono
parents:
diff changeset
334 const char *
kono
parents:
diff changeset
335 gimple_decl_printable_name (tree decl, int verbosity)
kono
parents:
diff changeset
336 {
kono
parents:
diff changeset
337 if (!DECL_NAME (decl))
kono
parents:
diff changeset
338 return NULL;
kono
parents:
diff changeset
339
kono
parents:
diff changeset
340 if (HAS_DECL_ASSEMBLER_NAME_P (decl) && DECL_ASSEMBLER_NAME_SET_P (decl))
kono
parents:
diff changeset
341 {
kono
parents:
diff changeset
342 int dmgl_opts = DMGL_NO_OPTS;
kono
parents:
diff changeset
343
kono
parents:
diff changeset
344 if (verbosity >= 2)
kono
parents:
diff changeset
345 {
kono
parents:
diff changeset
346 dmgl_opts = DMGL_VERBOSE
kono
parents:
diff changeset
347 | DMGL_ANSI
kono
parents:
diff changeset
348 | DMGL_GNU_V3
kono
parents:
diff changeset
349 | DMGL_RET_POSTFIX;
kono
parents:
diff changeset
350 if (TREE_CODE (decl) == FUNCTION_DECL)
kono
parents:
diff changeset
351 dmgl_opts |= DMGL_PARAMS;
kono
parents:
diff changeset
352 }
kono
parents:
diff changeset
353
kono
parents:
diff changeset
354 const char *mangled_str
kono
parents:
diff changeset
355 = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME_RAW (decl));
kono
parents:
diff changeset
356 const char *str = cplus_demangle_v3 (mangled_str, dmgl_opts);
kono
parents:
diff changeset
357 return str ? str : mangled_str;
kono
parents:
diff changeset
358 }
kono
parents:
diff changeset
359
kono
parents:
diff changeset
360 return IDENTIFIER_POINTER (DECL_NAME (decl));
kono
parents:
diff changeset
361 }
kono
parents:
diff changeset
362
kono
parents:
diff changeset
363
kono
parents:
diff changeset
364 /* Create a new VAR_DECL and copy information from VAR to it. */
kono
parents:
diff changeset
365
kono
parents:
diff changeset
366 tree
kono
parents:
diff changeset
367 copy_var_decl (tree var, tree name, tree type)
kono
parents:
diff changeset
368 {
kono
parents:
diff changeset
369 tree copy = build_decl (DECL_SOURCE_LOCATION (var), VAR_DECL, name, type);
kono
parents:
diff changeset
370
kono
parents:
diff changeset
371 TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (var);
kono
parents:
diff changeset
372 TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (var);
kono
parents:
diff changeset
373 DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (var);
kono
parents:
diff changeset
374 DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (var);
kono
parents:
diff changeset
375 DECL_IGNORED_P (copy) = DECL_IGNORED_P (var);
kono
parents:
diff changeset
376 DECL_CONTEXT (copy) = DECL_CONTEXT (var);
kono
parents:
diff changeset
377 TREE_NO_WARNING (copy) = TREE_NO_WARNING (var);
kono
parents:
diff changeset
378 TREE_USED (copy) = 1;
kono
parents:
diff changeset
379 DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
kono
parents:
diff changeset
380 DECL_ATTRIBUTES (copy) = DECL_ATTRIBUTES (var);
kono
parents:
diff changeset
381 if (DECL_USER_ALIGN (var))
kono
parents:
diff changeset
382 {
kono
parents:
diff changeset
383 SET_DECL_ALIGN (copy, DECL_ALIGN (var));
kono
parents:
diff changeset
384 DECL_USER_ALIGN (copy) = 1;
kono
parents:
diff changeset
385 }
kono
parents:
diff changeset
386
kono
parents:
diff changeset
387 return copy;
kono
parents:
diff changeset
388 }
kono
parents:
diff changeset
389
kono
parents:
diff changeset
390 /* Strip off a legitimate source ending from the input string NAME of
kono
parents:
diff changeset
391 length LEN. Rather than having to know the names used by all of
kono
parents:
diff changeset
392 our front ends, we strip off an ending of a period followed by
kono
parents:
diff changeset
393 up to four characters. (like ".cpp".) */
kono
parents:
diff changeset
394
kono
parents:
diff changeset
395 static inline void
kono
parents:
diff changeset
396 remove_suffix (char *name, int len)
kono
parents:
diff changeset
397 {
kono
parents:
diff changeset
398 int i;
kono
parents:
diff changeset
399
kono
parents:
diff changeset
400 for (i = 2; i < 7 && len > i; i++)
kono
parents:
diff changeset
401 {
kono
parents:
diff changeset
402 if (name[len - i] == '.')
kono
parents:
diff changeset
403 {
kono
parents:
diff changeset
404 name[len - i] = '\0';
kono
parents:
diff changeset
405 break;
kono
parents:
diff changeset
406 }
kono
parents:
diff changeset
407 }
kono
parents:
diff changeset
408 }
kono
parents:
diff changeset
409
kono
parents:
diff changeset
410 /* Create a new temporary name with PREFIX. Return an identifier. */
kono
parents:
diff changeset
411
kono
parents:
diff changeset
412 static GTY(()) unsigned int tmp_var_id_num;
kono
parents:
diff changeset
413
kono
parents:
diff changeset
414 tree
kono
parents:
diff changeset
415 create_tmp_var_name (const char *prefix)
kono
parents:
diff changeset
416 {
kono
parents:
diff changeset
417 char *tmp_name;
kono
parents:
diff changeset
418
kono
parents:
diff changeset
419 if (prefix)
kono
parents:
diff changeset
420 {
kono
parents:
diff changeset
421 char *preftmp = ASTRDUP (prefix);
kono
parents:
diff changeset
422
kono
parents:
diff changeset
423 remove_suffix (preftmp, strlen (preftmp));
kono
parents:
diff changeset
424 clean_symbol_name (preftmp);
kono
parents:
diff changeset
425
kono
parents:
diff changeset
426 prefix = preftmp;
kono
parents:
diff changeset
427 }
kono
parents:
diff changeset
428
kono
parents:
diff changeset
429 ASM_FORMAT_PRIVATE_NAME (tmp_name, prefix ? prefix : "T", tmp_var_id_num++);
kono
parents:
diff changeset
430 return get_identifier (tmp_name);
kono
parents:
diff changeset
431 }
kono
parents:
diff changeset
432
kono
parents:
diff changeset
433 /* Create a new temporary variable declaration of type TYPE.
kono
parents:
diff changeset
434 Do NOT push it into the current binding. */
kono
parents:
diff changeset
435
kono
parents:
diff changeset
436 tree
kono
parents:
diff changeset
437 create_tmp_var_raw (tree type, const char *prefix)
kono
parents:
diff changeset
438 {
kono
parents:
diff changeset
439 tree tmp_var;
kono
parents:
diff changeset
440
kono
parents:
diff changeset
441 tmp_var = build_decl (input_location,
kono
parents:
diff changeset
442 VAR_DECL, prefix ? create_tmp_var_name (prefix) : NULL,
kono
parents:
diff changeset
443 type);
kono
parents:
diff changeset
444
kono
parents:
diff changeset
445 /* The variable was declared by the compiler. */
kono
parents:
diff changeset
446 DECL_ARTIFICIAL (tmp_var) = 1;
kono
parents:
diff changeset
447 /* And we don't want debug info for it. */
kono
parents:
diff changeset
448 DECL_IGNORED_P (tmp_var) = 1;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
449 /* And we don't want even the fancy names of those printed in
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
450 -fdump-final-insns= dumps. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
451 DECL_NAMELESS (tmp_var) = 1;
111
kono
parents:
diff changeset
452
kono
parents:
diff changeset
453 /* Make the variable writable. */
kono
parents:
diff changeset
454 TREE_READONLY (tmp_var) = 0;
kono
parents:
diff changeset
455
kono
parents:
diff changeset
456 DECL_EXTERNAL (tmp_var) = 0;
kono
parents:
diff changeset
457 TREE_STATIC (tmp_var) = 0;
kono
parents:
diff changeset
458 TREE_USED (tmp_var) = 1;
kono
parents:
diff changeset
459
kono
parents:
diff changeset
460 return tmp_var;
kono
parents:
diff changeset
461 }
kono
parents:
diff changeset
462
kono
parents:
diff changeset
463 /* Create a new temporary variable declaration of type TYPE. DO push the
kono
parents:
diff changeset
464 variable into the current binding. Further, assume that this is called
kono
parents:
diff changeset
465 only from gimplification or optimization, at which point the creation of
kono
parents:
diff changeset
466 certain types are bugs. */
kono
parents:
diff changeset
467
kono
parents:
diff changeset
468 tree
kono
parents:
diff changeset
469 create_tmp_var (tree type, const char *prefix)
kono
parents:
diff changeset
470 {
kono
parents:
diff changeset
471 tree tmp_var;
kono
parents:
diff changeset
472
kono
parents:
diff changeset
473 /* We don't allow types that are addressable (meaning we can't make copies),
kono
parents:
diff changeset
474 or incomplete. We also used to reject every variable size objects here,
kono
parents:
diff changeset
475 but now support those for which a constant upper bound can be obtained.
kono
parents:
diff changeset
476 The processing for variable sizes is performed in gimple_add_tmp_var,
kono
parents:
diff changeset
477 point at which it really matters and possibly reached via paths not going
kono
parents:
diff changeset
478 through this function, e.g. after direct calls to create_tmp_var_raw. */
kono
parents:
diff changeset
479 gcc_assert (!TREE_ADDRESSABLE (type) && COMPLETE_TYPE_P (type));
kono
parents:
diff changeset
480
kono
parents:
diff changeset
481 tmp_var = create_tmp_var_raw (type, prefix);
kono
parents:
diff changeset
482 gimple_add_tmp_var (tmp_var);
kono
parents:
diff changeset
483 return tmp_var;
kono
parents:
diff changeset
484 }
kono
parents:
diff changeset
485
kono
parents:
diff changeset
486 /* Create a new temporary variable declaration of type TYPE by calling
kono
parents:
diff changeset
487 create_tmp_var and if TYPE is a vector or a complex number, mark the new
kono
parents:
diff changeset
488 temporary as gimple register. */
kono
parents:
diff changeset
489
kono
parents:
diff changeset
490 tree
kono
parents:
diff changeset
491 create_tmp_reg (tree type, const char *prefix)
kono
parents:
diff changeset
492 {
kono
parents:
diff changeset
493 tree tmp;
kono
parents:
diff changeset
494
kono
parents:
diff changeset
495 tmp = create_tmp_var (type, prefix);
kono
parents:
diff changeset
496 if (TREE_CODE (type) == COMPLEX_TYPE
kono
parents:
diff changeset
497 || TREE_CODE (type) == VECTOR_TYPE)
kono
parents:
diff changeset
498 DECL_GIMPLE_REG_P (tmp) = 1;
kono
parents:
diff changeset
499
kono
parents:
diff changeset
500 return tmp;
kono
parents:
diff changeset
501 }
kono
parents:
diff changeset
502
kono
parents:
diff changeset
503 /* Create a new temporary variable declaration of type TYPE by calling
kono
parents:
diff changeset
504 create_tmp_var and if TYPE is a vector or a complex number, mark the new
kono
parents:
diff changeset
505 temporary as gimple register. */
kono
parents:
diff changeset
506
kono
parents:
diff changeset
507 tree
kono
parents:
diff changeset
508 create_tmp_reg_fn (struct function *fn, tree type, const char *prefix)
kono
parents:
diff changeset
509 {
kono
parents:
diff changeset
510 tree tmp;
kono
parents:
diff changeset
511
kono
parents:
diff changeset
512 tmp = create_tmp_var_raw (type, prefix);
kono
parents:
diff changeset
513 gimple_add_tmp_var_fn (fn, tmp);
kono
parents:
diff changeset
514 if (TREE_CODE (type) == COMPLEX_TYPE
kono
parents:
diff changeset
515 || TREE_CODE (type) == VECTOR_TYPE)
kono
parents:
diff changeset
516 DECL_GIMPLE_REG_P (tmp) = 1;
kono
parents:
diff changeset
517
kono
parents:
diff changeset
518 return tmp;
kono
parents:
diff changeset
519 }
kono
parents:
diff changeset
520
kono
parents:
diff changeset
521
kono
parents:
diff changeset
522 /* ----- Expression related ----- */
kono
parents:
diff changeset
523
kono
parents:
diff changeset
524 /* Extract the operands and code for expression EXPR into *SUBCODE_P,
kono
parents:
diff changeset
525 *OP1_P, *OP2_P and *OP3_P respectively. */
kono
parents:
diff changeset
526
kono
parents:
diff changeset
527 void
kono
parents:
diff changeset
528 extract_ops_from_tree (tree expr, enum tree_code *subcode_p, tree *op1_p,
kono
parents:
diff changeset
529 tree *op2_p, tree *op3_p)
kono
parents:
diff changeset
530 {
kono
parents:
diff changeset
531 enum gimple_rhs_class grhs_class;
kono
parents:
diff changeset
532
kono
parents:
diff changeset
533 *subcode_p = TREE_CODE (expr);
kono
parents:
diff changeset
534 grhs_class = get_gimple_rhs_class (*subcode_p);
kono
parents:
diff changeset
535
kono
parents:
diff changeset
536 if (grhs_class == GIMPLE_TERNARY_RHS)
kono
parents:
diff changeset
537 {
kono
parents:
diff changeset
538 *op1_p = TREE_OPERAND (expr, 0);
kono
parents:
diff changeset
539 *op2_p = TREE_OPERAND (expr, 1);
kono
parents:
diff changeset
540 *op3_p = TREE_OPERAND (expr, 2);
kono
parents:
diff changeset
541 }
kono
parents:
diff changeset
542 else if (grhs_class == GIMPLE_BINARY_RHS)
kono
parents:
diff changeset
543 {
kono
parents:
diff changeset
544 *op1_p = TREE_OPERAND (expr, 0);
kono
parents:
diff changeset
545 *op2_p = TREE_OPERAND (expr, 1);
kono
parents:
diff changeset
546 *op3_p = NULL_TREE;
kono
parents:
diff changeset
547 }
kono
parents:
diff changeset
548 else if (grhs_class == GIMPLE_UNARY_RHS)
kono
parents:
diff changeset
549 {
kono
parents:
diff changeset
550 *op1_p = TREE_OPERAND (expr, 0);
kono
parents:
diff changeset
551 *op2_p = NULL_TREE;
kono
parents:
diff changeset
552 *op3_p = NULL_TREE;
kono
parents:
diff changeset
553 }
kono
parents:
diff changeset
554 else if (grhs_class == GIMPLE_SINGLE_RHS)
kono
parents:
diff changeset
555 {
kono
parents:
diff changeset
556 *op1_p = expr;
kono
parents:
diff changeset
557 *op2_p = NULL_TREE;
kono
parents:
diff changeset
558 *op3_p = NULL_TREE;
kono
parents:
diff changeset
559 }
kono
parents:
diff changeset
560 else
kono
parents:
diff changeset
561 gcc_unreachable ();
kono
parents:
diff changeset
562 }
kono
parents:
diff changeset
563
kono
parents:
diff changeset
564 /* Extract operands for a GIMPLE_COND statement out of COND_EXPR tree COND. */
kono
parents:
diff changeset
565
kono
parents:
diff changeset
566 void
kono
parents:
diff changeset
567 gimple_cond_get_ops_from_tree (tree cond, enum tree_code *code_p,
kono
parents:
diff changeset
568 tree *lhs_p, tree *rhs_p)
kono
parents:
diff changeset
569 {
kono
parents:
diff changeset
570 gcc_assert (COMPARISON_CLASS_P (cond)
kono
parents:
diff changeset
571 || TREE_CODE (cond) == TRUTH_NOT_EXPR
kono
parents:
diff changeset
572 || is_gimple_min_invariant (cond)
kono
parents:
diff changeset
573 || SSA_VAR_P (cond));
kono
parents:
diff changeset
574
kono
parents:
diff changeset
575 extract_ops_from_tree (cond, code_p, lhs_p, rhs_p);
kono
parents:
diff changeset
576
kono
parents:
diff changeset
577 /* Canonicalize conditionals of the form 'if (!VAL)'. */
kono
parents:
diff changeset
578 if (*code_p == TRUTH_NOT_EXPR)
kono
parents:
diff changeset
579 {
kono
parents:
diff changeset
580 *code_p = EQ_EXPR;
kono
parents:
diff changeset
581 gcc_assert (*lhs_p && *rhs_p == NULL_TREE);
kono
parents:
diff changeset
582 *rhs_p = build_zero_cst (TREE_TYPE (*lhs_p));
kono
parents:
diff changeset
583 }
kono
parents:
diff changeset
584 /* Canonicalize conditionals of the form 'if (VAL)' */
kono
parents:
diff changeset
585 else if (TREE_CODE_CLASS (*code_p) != tcc_comparison)
kono
parents:
diff changeset
586 {
kono
parents:
diff changeset
587 *code_p = NE_EXPR;
kono
parents:
diff changeset
588 gcc_assert (*lhs_p && *rhs_p == NULL_TREE);
kono
parents:
diff changeset
589 *rhs_p = build_zero_cst (TREE_TYPE (*lhs_p));
kono
parents:
diff changeset
590 }
kono
parents:
diff changeset
591 }
kono
parents:
diff changeset
592
kono
parents:
diff changeset
593 /* Return true if T is a valid LHS for a GIMPLE assignment expression. */
kono
parents:
diff changeset
594
kono
parents:
diff changeset
595 bool
kono
parents:
diff changeset
596 is_gimple_lvalue (tree t)
kono
parents:
diff changeset
597 {
kono
parents:
diff changeset
598 return (is_gimple_addressable (t)
kono
parents:
diff changeset
599 || TREE_CODE (t) == WITH_SIZE_EXPR
kono
parents:
diff changeset
600 /* These are complex lvalues, but don't have addresses, so they
kono
parents:
diff changeset
601 go here. */
kono
parents:
diff changeset
602 || TREE_CODE (t) == BIT_FIELD_REF);
kono
parents:
diff changeset
603 }
kono
parents:
diff changeset
604
kono
parents:
diff changeset
605 /* Return true if T is a GIMPLE condition. */
kono
parents:
diff changeset
606
kono
parents:
diff changeset
607 bool
kono
parents:
diff changeset
608 is_gimple_condexpr (tree t)
kono
parents:
diff changeset
609 {
kono
parents:
diff changeset
610 return (is_gimple_val (t) || (COMPARISON_CLASS_P (t)
kono
parents:
diff changeset
611 && !tree_could_throw_p (t)
kono
parents:
diff changeset
612 && is_gimple_val (TREE_OPERAND (t, 0))
kono
parents:
diff changeset
613 && is_gimple_val (TREE_OPERAND (t, 1))));
kono
parents:
diff changeset
614 }
kono
parents:
diff changeset
615
kono
parents:
diff changeset
616 /* Return true if T is a gimple address. */
kono
parents:
diff changeset
617
kono
parents:
diff changeset
618 bool
kono
parents:
diff changeset
619 is_gimple_address (const_tree t)
kono
parents:
diff changeset
620 {
kono
parents:
diff changeset
621 tree op;
kono
parents:
diff changeset
622
kono
parents:
diff changeset
623 if (TREE_CODE (t) != ADDR_EXPR)
kono
parents:
diff changeset
624 return false;
kono
parents:
diff changeset
625
kono
parents:
diff changeset
626 op = TREE_OPERAND (t, 0);
kono
parents:
diff changeset
627 while (handled_component_p (op))
kono
parents:
diff changeset
628 {
kono
parents:
diff changeset
629 if ((TREE_CODE (op) == ARRAY_REF
kono
parents:
diff changeset
630 || TREE_CODE (op) == ARRAY_RANGE_REF)
kono
parents:
diff changeset
631 && !is_gimple_val (TREE_OPERAND (op, 1)))
kono
parents:
diff changeset
632 return false;
kono
parents:
diff changeset
633
kono
parents:
diff changeset
634 op = TREE_OPERAND (op, 0);
kono
parents:
diff changeset
635 }
kono
parents:
diff changeset
636
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
637 if (CONSTANT_CLASS_P (op)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
638 || TREE_CODE (op) == TARGET_MEM_REF
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
639 || TREE_CODE (op) == MEM_REF)
111
kono
parents:
diff changeset
640 return true;
kono
parents:
diff changeset
641
kono
parents:
diff changeset
642 switch (TREE_CODE (op))
kono
parents:
diff changeset
643 {
kono
parents:
diff changeset
644 case PARM_DECL:
kono
parents:
diff changeset
645 case RESULT_DECL:
kono
parents:
diff changeset
646 case LABEL_DECL:
kono
parents:
diff changeset
647 case FUNCTION_DECL:
kono
parents:
diff changeset
648 case VAR_DECL:
kono
parents:
diff changeset
649 case CONST_DECL:
kono
parents:
diff changeset
650 return true;
kono
parents:
diff changeset
651
kono
parents:
diff changeset
652 default:
kono
parents:
diff changeset
653 return false;
kono
parents:
diff changeset
654 }
kono
parents:
diff changeset
655 }
kono
parents:
diff changeset
656
kono
parents:
diff changeset
657 /* Return true if T is a gimple invariant address. */
kono
parents:
diff changeset
658
kono
parents:
diff changeset
659 bool
kono
parents:
diff changeset
660 is_gimple_invariant_address (const_tree t)
kono
parents:
diff changeset
661 {
kono
parents:
diff changeset
662 const_tree op;
kono
parents:
diff changeset
663
kono
parents:
diff changeset
664 if (TREE_CODE (t) != ADDR_EXPR)
kono
parents:
diff changeset
665 return false;
kono
parents:
diff changeset
666
kono
parents:
diff changeset
667 op = strip_invariant_refs (TREE_OPERAND (t, 0));
kono
parents:
diff changeset
668 if (!op)
kono
parents:
diff changeset
669 return false;
kono
parents:
diff changeset
670
kono
parents:
diff changeset
671 if (TREE_CODE (op) == MEM_REF)
kono
parents:
diff changeset
672 {
kono
parents:
diff changeset
673 const_tree op0 = TREE_OPERAND (op, 0);
kono
parents:
diff changeset
674 return (TREE_CODE (op0) == ADDR_EXPR
kono
parents:
diff changeset
675 && (CONSTANT_CLASS_P (TREE_OPERAND (op0, 0))
kono
parents:
diff changeset
676 || decl_address_invariant_p (TREE_OPERAND (op0, 0))));
kono
parents:
diff changeset
677 }
kono
parents:
diff changeset
678
kono
parents:
diff changeset
679 return CONSTANT_CLASS_P (op) || decl_address_invariant_p (op);
kono
parents:
diff changeset
680 }
kono
parents:
diff changeset
681
kono
parents:
diff changeset
682 /* Return true if T is a gimple invariant address at IPA level
kono
parents:
diff changeset
683 (so addresses of variables on stack are not allowed). */
kono
parents:
diff changeset
684
kono
parents:
diff changeset
685 bool
kono
parents:
diff changeset
686 is_gimple_ip_invariant_address (const_tree t)
kono
parents:
diff changeset
687 {
kono
parents:
diff changeset
688 const_tree op;
kono
parents:
diff changeset
689
kono
parents:
diff changeset
690 if (TREE_CODE (t) != ADDR_EXPR)
kono
parents:
diff changeset
691 return false;
kono
parents:
diff changeset
692
kono
parents:
diff changeset
693 op = strip_invariant_refs (TREE_OPERAND (t, 0));
kono
parents:
diff changeset
694 if (!op)
kono
parents:
diff changeset
695 return false;
kono
parents:
diff changeset
696
kono
parents:
diff changeset
697 if (TREE_CODE (op) == MEM_REF)
kono
parents:
diff changeset
698 {
kono
parents:
diff changeset
699 const_tree op0 = TREE_OPERAND (op, 0);
kono
parents:
diff changeset
700 return (TREE_CODE (op0) == ADDR_EXPR
kono
parents:
diff changeset
701 && (CONSTANT_CLASS_P (TREE_OPERAND (op0, 0))
kono
parents:
diff changeset
702 || decl_address_ip_invariant_p (TREE_OPERAND (op0, 0))));
kono
parents:
diff changeset
703 }
kono
parents:
diff changeset
704
kono
parents:
diff changeset
705 return CONSTANT_CLASS_P (op) || decl_address_ip_invariant_p (op);
kono
parents:
diff changeset
706 }
kono
parents:
diff changeset
707
kono
parents:
diff changeset
708 /* Return true if T is a GIMPLE minimal invariant. It's a restricted
kono
parents:
diff changeset
709 form of function invariant. */
kono
parents:
diff changeset
710
kono
parents:
diff changeset
711 bool
kono
parents:
diff changeset
712 is_gimple_min_invariant (const_tree t)
kono
parents:
diff changeset
713 {
kono
parents:
diff changeset
714 if (TREE_CODE (t) == ADDR_EXPR)
kono
parents:
diff changeset
715 return is_gimple_invariant_address (t);
kono
parents:
diff changeset
716
kono
parents:
diff changeset
717 return is_gimple_constant (t);
kono
parents:
diff changeset
718 }
kono
parents:
diff changeset
719
kono
parents:
diff changeset
720 /* Return true if T is a GIMPLE interprocedural invariant. It's a restricted
kono
parents:
diff changeset
721 form of gimple minimal invariant. */
kono
parents:
diff changeset
722
kono
parents:
diff changeset
723 bool
kono
parents:
diff changeset
724 is_gimple_ip_invariant (const_tree t)
kono
parents:
diff changeset
725 {
kono
parents:
diff changeset
726 if (TREE_CODE (t) == ADDR_EXPR)
kono
parents:
diff changeset
727 return is_gimple_ip_invariant_address (t);
kono
parents:
diff changeset
728
kono
parents:
diff changeset
729 return is_gimple_constant (t);
kono
parents:
diff changeset
730 }
kono
parents:
diff changeset
731
kono
parents:
diff changeset
732 /* Return true if T is a non-aggregate register variable. */
kono
parents:
diff changeset
733
kono
parents:
diff changeset
734 bool
kono
parents:
diff changeset
735 is_gimple_reg (tree t)
kono
parents:
diff changeset
736 {
kono
parents:
diff changeset
737 if (virtual_operand_p (t))
kono
parents:
diff changeset
738 return false;
kono
parents:
diff changeset
739
kono
parents:
diff changeset
740 if (TREE_CODE (t) == SSA_NAME)
kono
parents:
diff changeset
741 return true;
kono
parents:
diff changeset
742
kono
parents:
diff changeset
743 if (!is_gimple_variable (t))
kono
parents:
diff changeset
744 return false;
kono
parents:
diff changeset
745
kono
parents:
diff changeset
746 if (!is_gimple_reg_type (TREE_TYPE (t)))
kono
parents:
diff changeset
747 return false;
kono
parents:
diff changeset
748
kono
parents:
diff changeset
749 /* A volatile decl is not acceptable because we can't reuse it as
kono
parents:
diff changeset
750 needed. We need to copy it into a temp first. */
kono
parents:
diff changeset
751 if (TREE_THIS_VOLATILE (t))
kono
parents:
diff changeset
752 return false;
kono
parents:
diff changeset
753
kono
parents:
diff changeset
754 /* We define "registers" as things that can be renamed as needed,
kono
parents:
diff changeset
755 which with our infrastructure does not apply to memory. */
kono
parents:
diff changeset
756 if (needs_to_live_in_memory (t))
kono
parents:
diff changeset
757 return false;
kono
parents:
diff changeset
758
kono
parents:
diff changeset
759 /* Hard register variables are an interesting case. For those that
kono
parents:
diff changeset
760 are call-clobbered, we don't know where all the calls are, since
kono
parents:
diff changeset
761 we don't (want to) take into account which operations will turn
kono
parents:
diff changeset
762 into libcalls at the rtl level. For those that are call-saved,
kono
parents:
diff changeset
763 we don't currently model the fact that calls may in fact change
kono
parents:
diff changeset
764 global hard registers, nor do we examine ASM_CLOBBERS at the tree
kono
parents:
diff changeset
765 level, and so miss variable changes that might imply. All around,
kono
parents:
diff changeset
766 it seems safest to not do too much optimization with these at the
kono
parents:
diff changeset
767 tree level at all. We'll have to rely on the rtl optimizers to
kono
parents:
diff changeset
768 clean this up, as there we've got all the appropriate bits exposed. */
kono
parents:
diff changeset
769 if (TREE_CODE (t) == VAR_DECL && DECL_HARD_REGISTER (t))
kono
parents:
diff changeset
770 return false;
kono
parents:
diff changeset
771
kono
parents:
diff changeset
772 /* Complex and vector values must have been put into SSA-like form.
kono
parents:
diff changeset
773 That is, no assignments to the individual components. */
kono
parents:
diff changeset
774 if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE
kono
parents:
diff changeset
775 || TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
kono
parents:
diff changeset
776 return DECL_GIMPLE_REG_P (t);
kono
parents:
diff changeset
777
kono
parents:
diff changeset
778 return true;
kono
parents:
diff changeset
779 }
kono
parents:
diff changeset
780
kono
parents:
diff changeset
781
kono
parents:
diff changeset
782 /* Return true if T is a GIMPLE rvalue, i.e. an identifier or a constant. */
kono
parents:
diff changeset
783
kono
parents:
diff changeset
784 bool
kono
parents:
diff changeset
785 is_gimple_val (tree t)
kono
parents:
diff changeset
786 {
kono
parents:
diff changeset
787 /* Make loads from volatiles and memory vars explicit. */
kono
parents:
diff changeset
788 if (is_gimple_variable (t)
kono
parents:
diff changeset
789 && is_gimple_reg_type (TREE_TYPE (t))
kono
parents:
diff changeset
790 && !is_gimple_reg (t))
kono
parents:
diff changeset
791 return false;
kono
parents:
diff changeset
792
kono
parents:
diff changeset
793 return (is_gimple_variable (t) || is_gimple_min_invariant (t));
kono
parents:
diff changeset
794 }
kono
parents:
diff changeset
795
kono
parents:
diff changeset
796 /* Similarly, but accept hard registers as inputs to asm statements. */
kono
parents:
diff changeset
797
kono
parents:
diff changeset
798 bool
kono
parents:
diff changeset
799 is_gimple_asm_val (tree t)
kono
parents:
diff changeset
800 {
kono
parents:
diff changeset
801 if (TREE_CODE (t) == VAR_DECL && DECL_HARD_REGISTER (t))
kono
parents:
diff changeset
802 return true;
kono
parents:
diff changeset
803
kono
parents:
diff changeset
804 return is_gimple_val (t);
kono
parents:
diff changeset
805 }
kono
parents:
diff changeset
806
kono
parents:
diff changeset
807 /* Return true if T is a GIMPLE minimal lvalue. */
kono
parents:
diff changeset
808
kono
parents:
diff changeset
809 bool
kono
parents:
diff changeset
810 is_gimple_min_lval (tree t)
kono
parents:
diff changeset
811 {
kono
parents:
diff changeset
812 if (!(t = CONST_CAST_TREE (strip_invariant_refs (t))))
kono
parents:
diff changeset
813 return false;
kono
parents:
diff changeset
814 return (is_gimple_id (t) || TREE_CODE (t) == MEM_REF);
kono
parents:
diff changeset
815 }
kono
parents:
diff changeset
816
kono
parents:
diff changeset
817 /* Return true if T is a valid function operand of a CALL_EXPR. */
kono
parents:
diff changeset
818
kono
parents:
diff changeset
819 bool
kono
parents:
diff changeset
820 is_gimple_call_addr (tree t)
kono
parents:
diff changeset
821 {
kono
parents:
diff changeset
822 return (TREE_CODE (t) == OBJ_TYPE_REF || is_gimple_val (t));
kono
parents:
diff changeset
823 }
kono
parents:
diff changeset
824
kono
parents:
diff changeset
825 /* Return true if T is a valid address operand of a MEM_REF. */
kono
parents:
diff changeset
826
kono
parents:
diff changeset
827 bool
kono
parents:
diff changeset
828 is_gimple_mem_ref_addr (tree t)
kono
parents:
diff changeset
829 {
kono
parents:
diff changeset
830 return (is_gimple_reg (t)
kono
parents:
diff changeset
831 || TREE_CODE (t) == INTEGER_CST
kono
parents:
diff changeset
832 || (TREE_CODE (t) == ADDR_EXPR
kono
parents:
diff changeset
833 && (CONSTANT_CLASS_P (TREE_OPERAND (t, 0))
kono
parents:
diff changeset
834 || decl_address_invariant_p (TREE_OPERAND (t, 0)))));
kono
parents:
diff changeset
835 }
kono
parents:
diff changeset
836
kono
parents:
diff changeset
837 /* Hold trees marked addressable during expand. */
kono
parents:
diff changeset
838
kono
parents:
diff changeset
839 static hash_set<tree> *mark_addressable_queue;
kono
parents:
diff changeset
840
kono
parents:
diff changeset
841 /* Mark X as addressable or queue it up if called during expand. We
kono
parents:
diff changeset
842 don't want to apply it immediately during expand because decls are
kono
parents:
diff changeset
843 made addressable at that point due to RTL-only concerns, such as
kono
parents:
diff changeset
844 uses of memcpy for block moves, and TREE_ADDRESSABLE changes
kono
parents:
diff changeset
845 is_gimple_reg, which might make it seem like a variable that used
kono
parents:
diff changeset
846 to be a gimple_reg shouldn't have been an SSA name. So we queue up
kono
parents:
diff changeset
847 this flag setting and only apply it when we're done with GIMPLE and
kono
parents:
diff changeset
848 only RTL issues matter. */
kono
parents:
diff changeset
849
kono
parents:
diff changeset
850 static void
kono
parents:
diff changeset
851 mark_addressable_1 (tree x)
kono
parents:
diff changeset
852 {
kono
parents:
diff changeset
853 if (!currently_expanding_to_rtl)
kono
parents:
diff changeset
854 {
kono
parents:
diff changeset
855 TREE_ADDRESSABLE (x) = 1;
kono
parents:
diff changeset
856 return;
kono
parents:
diff changeset
857 }
kono
parents:
diff changeset
858
kono
parents:
diff changeset
859 if (!mark_addressable_queue)
kono
parents:
diff changeset
860 mark_addressable_queue = new hash_set<tree>();
kono
parents:
diff changeset
861 mark_addressable_queue->add (x);
kono
parents:
diff changeset
862 }
kono
parents:
diff changeset
863
kono
parents:
diff changeset
864 /* Adaptor for mark_addressable_1 for use in hash_set traversal. */
kono
parents:
diff changeset
865
kono
parents:
diff changeset
866 bool
kono
parents:
diff changeset
867 mark_addressable_2 (tree const &x, void * ATTRIBUTE_UNUSED = NULL)
kono
parents:
diff changeset
868 {
kono
parents:
diff changeset
869 mark_addressable_1 (x);
kono
parents:
diff changeset
870 return false;
kono
parents:
diff changeset
871 }
kono
parents:
diff changeset
872
kono
parents:
diff changeset
873 /* Mark all queued trees as addressable, and empty the queue. To be
kono
parents:
diff changeset
874 called right after clearing CURRENTLY_EXPANDING_TO_RTL. */
kono
parents:
diff changeset
875
kono
parents:
diff changeset
876 void
kono
parents:
diff changeset
877 flush_mark_addressable_queue ()
kono
parents:
diff changeset
878 {
kono
parents:
diff changeset
879 gcc_assert (!currently_expanding_to_rtl);
kono
parents:
diff changeset
880 if (mark_addressable_queue)
kono
parents:
diff changeset
881 {
kono
parents:
diff changeset
882 mark_addressable_queue->traverse<void*, mark_addressable_2> (NULL);
kono
parents:
diff changeset
883 delete mark_addressable_queue;
kono
parents:
diff changeset
884 mark_addressable_queue = NULL;
kono
parents:
diff changeset
885 }
kono
parents:
diff changeset
886 }
kono
parents:
diff changeset
887
kono
parents:
diff changeset
888 /* Mark X addressable. Unlike the langhook we expect X to be in gimple
kono
parents:
diff changeset
889 form and we don't do any syntax checking. */
kono
parents:
diff changeset
890
kono
parents:
diff changeset
891 void
kono
parents:
diff changeset
892 mark_addressable (tree x)
kono
parents:
diff changeset
893 {
kono
parents:
diff changeset
894 while (handled_component_p (x))
kono
parents:
diff changeset
895 x = TREE_OPERAND (x, 0);
kono
parents:
diff changeset
896 if (TREE_CODE (x) == MEM_REF
kono
parents:
diff changeset
897 && TREE_CODE (TREE_OPERAND (x, 0)) == ADDR_EXPR)
kono
parents:
diff changeset
898 x = TREE_OPERAND (TREE_OPERAND (x, 0), 0);
kono
parents:
diff changeset
899 if (!VAR_P (x)
kono
parents:
diff changeset
900 && TREE_CODE (x) != PARM_DECL
kono
parents:
diff changeset
901 && TREE_CODE (x) != RESULT_DECL)
kono
parents:
diff changeset
902 return;
kono
parents:
diff changeset
903 mark_addressable_1 (x);
kono
parents:
diff changeset
904
kono
parents:
diff changeset
905 /* Also mark the artificial SSA_NAME that points to the partition of X. */
kono
parents:
diff changeset
906 if (TREE_CODE (x) == VAR_DECL
kono
parents:
diff changeset
907 && !DECL_EXTERNAL (x)
kono
parents:
diff changeset
908 && !TREE_STATIC (x)
kono
parents:
diff changeset
909 && cfun->gimple_df != NULL
kono
parents:
diff changeset
910 && cfun->gimple_df->decls_to_pointers != NULL)
kono
parents:
diff changeset
911 {
kono
parents:
diff changeset
912 tree *namep = cfun->gimple_df->decls_to_pointers->get (x);
kono
parents:
diff changeset
913 if (namep)
kono
parents:
diff changeset
914 mark_addressable_1 (*namep);
kono
parents:
diff changeset
915 }
kono
parents:
diff changeset
916 }
kono
parents:
diff changeset
917
kono
parents:
diff changeset
918 /* Returns true iff T is a valid RHS for an assignment to a renamed
kono
parents:
diff changeset
919 user -- or front-end generated artificial -- variable. */
kono
parents:
diff changeset
920
kono
parents:
diff changeset
921 bool
kono
parents:
diff changeset
922 is_gimple_reg_rhs (tree t)
kono
parents:
diff changeset
923 {
kono
parents:
diff changeset
924 return get_gimple_rhs_class (TREE_CODE (t)) != GIMPLE_INVALID_RHS;
kono
parents:
diff changeset
925 }
kono
parents:
diff changeset
926
kono
parents:
diff changeset
927 #include "gt-gimple-expr.h"