annotate gcc/gimple-expr.c @ 127:4c56639505ff

fix function.c and add CbC-example Makefile
author mir3636
date Wed, 11 Apr 2018 18:46:58 +0900
parents 04ced10e8804
children 84e7813d76e9
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
kono
parents:
diff changeset
3 Copyright (C) 2007-2017 Free Software Foundation, Inc.
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;
kono
parents:
diff changeset
449
kono
parents:
diff changeset
450 /* Make the variable writable. */
kono
parents:
diff changeset
451 TREE_READONLY (tmp_var) = 0;
kono
parents:
diff changeset
452
kono
parents:
diff changeset
453 DECL_EXTERNAL (tmp_var) = 0;
kono
parents:
diff changeset
454 TREE_STATIC (tmp_var) = 0;
kono
parents:
diff changeset
455 TREE_USED (tmp_var) = 1;
kono
parents:
diff changeset
456
kono
parents:
diff changeset
457 return tmp_var;
kono
parents:
diff changeset
458 }
kono
parents:
diff changeset
459
kono
parents:
diff changeset
460 /* Create a new temporary variable declaration of type TYPE. DO push the
kono
parents:
diff changeset
461 variable into the current binding. Further, assume that this is called
kono
parents:
diff changeset
462 only from gimplification or optimization, at which point the creation of
kono
parents:
diff changeset
463 certain types are bugs. */
kono
parents:
diff changeset
464
kono
parents:
diff changeset
465 tree
kono
parents:
diff changeset
466 create_tmp_var (tree type, const char *prefix)
kono
parents:
diff changeset
467 {
kono
parents:
diff changeset
468 tree tmp_var;
kono
parents:
diff changeset
469
kono
parents:
diff changeset
470 /* We don't allow types that are addressable (meaning we can't make copies),
kono
parents:
diff changeset
471 or incomplete. We also used to reject every variable size objects here,
kono
parents:
diff changeset
472 but now support those for which a constant upper bound can be obtained.
kono
parents:
diff changeset
473 The processing for variable sizes is performed in gimple_add_tmp_var,
kono
parents:
diff changeset
474 point at which it really matters and possibly reached via paths not going
kono
parents:
diff changeset
475 through this function, e.g. after direct calls to create_tmp_var_raw. */
kono
parents:
diff changeset
476 gcc_assert (!TREE_ADDRESSABLE (type) && COMPLETE_TYPE_P (type));
kono
parents:
diff changeset
477
kono
parents:
diff changeset
478 tmp_var = create_tmp_var_raw (type, prefix);
kono
parents:
diff changeset
479 gimple_add_tmp_var (tmp_var);
kono
parents:
diff changeset
480 return tmp_var;
kono
parents:
diff changeset
481 }
kono
parents:
diff changeset
482
kono
parents:
diff changeset
483 /* Create a new temporary variable declaration of type TYPE by calling
kono
parents:
diff changeset
484 create_tmp_var and if TYPE is a vector or a complex number, mark the new
kono
parents:
diff changeset
485 temporary as gimple register. */
kono
parents:
diff changeset
486
kono
parents:
diff changeset
487 tree
kono
parents:
diff changeset
488 create_tmp_reg (tree type, const char *prefix)
kono
parents:
diff changeset
489 {
kono
parents:
diff changeset
490 tree tmp;
kono
parents:
diff changeset
491
kono
parents:
diff changeset
492 tmp = create_tmp_var (type, prefix);
kono
parents:
diff changeset
493 if (TREE_CODE (type) == COMPLEX_TYPE
kono
parents:
diff changeset
494 || TREE_CODE (type) == VECTOR_TYPE)
kono
parents:
diff changeset
495 DECL_GIMPLE_REG_P (tmp) = 1;
kono
parents:
diff changeset
496
kono
parents:
diff changeset
497 return tmp;
kono
parents:
diff changeset
498 }
kono
parents:
diff changeset
499
kono
parents:
diff changeset
500 /* Create a new temporary variable declaration of type TYPE by calling
kono
parents:
diff changeset
501 create_tmp_var and if TYPE is a vector or a complex number, mark the new
kono
parents:
diff changeset
502 temporary as gimple register. */
kono
parents:
diff changeset
503
kono
parents:
diff changeset
504 tree
kono
parents:
diff changeset
505 create_tmp_reg_fn (struct function *fn, tree type, const char *prefix)
kono
parents:
diff changeset
506 {
kono
parents:
diff changeset
507 tree tmp;
kono
parents:
diff changeset
508
kono
parents:
diff changeset
509 tmp = create_tmp_var_raw (type, prefix);
kono
parents:
diff changeset
510 gimple_add_tmp_var_fn (fn, tmp);
kono
parents:
diff changeset
511 if (TREE_CODE (type) == COMPLEX_TYPE
kono
parents:
diff changeset
512 || TREE_CODE (type) == VECTOR_TYPE)
kono
parents:
diff changeset
513 DECL_GIMPLE_REG_P (tmp) = 1;
kono
parents:
diff changeset
514
kono
parents:
diff changeset
515 return tmp;
kono
parents:
diff changeset
516 }
kono
parents:
diff changeset
517
kono
parents:
diff changeset
518
kono
parents:
diff changeset
519 /* ----- Expression related ----- */
kono
parents:
diff changeset
520
kono
parents:
diff changeset
521 /* Extract the operands and code for expression EXPR into *SUBCODE_P,
kono
parents:
diff changeset
522 *OP1_P, *OP2_P and *OP3_P respectively. */
kono
parents:
diff changeset
523
kono
parents:
diff changeset
524 void
kono
parents:
diff changeset
525 extract_ops_from_tree (tree expr, enum tree_code *subcode_p, tree *op1_p,
kono
parents:
diff changeset
526 tree *op2_p, tree *op3_p)
kono
parents:
diff changeset
527 {
kono
parents:
diff changeset
528 enum gimple_rhs_class grhs_class;
kono
parents:
diff changeset
529
kono
parents:
diff changeset
530 *subcode_p = TREE_CODE (expr);
kono
parents:
diff changeset
531 grhs_class = get_gimple_rhs_class (*subcode_p);
kono
parents:
diff changeset
532
kono
parents:
diff changeset
533 if (grhs_class == GIMPLE_TERNARY_RHS)
kono
parents:
diff changeset
534 {
kono
parents:
diff changeset
535 *op1_p = TREE_OPERAND (expr, 0);
kono
parents:
diff changeset
536 *op2_p = TREE_OPERAND (expr, 1);
kono
parents:
diff changeset
537 *op3_p = TREE_OPERAND (expr, 2);
kono
parents:
diff changeset
538 }
kono
parents:
diff changeset
539 else if (grhs_class == GIMPLE_BINARY_RHS)
kono
parents:
diff changeset
540 {
kono
parents:
diff changeset
541 *op1_p = TREE_OPERAND (expr, 0);
kono
parents:
diff changeset
542 *op2_p = TREE_OPERAND (expr, 1);
kono
parents:
diff changeset
543 *op3_p = NULL_TREE;
kono
parents:
diff changeset
544 }
kono
parents:
diff changeset
545 else if (grhs_class == GIMPLE_UNARY_RHS)
kono
parents:
diff changeset
546 {
kono
parents:
diff changeset
547 *op1_p = TREE_OPERAND (expr, 0);
kono
parents:
diff changeset
548 *op2_p = NULL_TREE;
kono
parents:
diff changeset
549 *op3_p = NULL_TREE;
kono
parents:
diff changeset
550 }
kono
parents:
diff changeset
551 else if (grhs_class == GIMPLE_SINGLE_RHS)
kono
parents:
diff changeset
552 {
kono
parents:
diff changeset
553 *op1_p = expr;
kono
parents:
diff changeset
554 *op2_p = NULL_TREE;
kono
parents:
diff changeset
555 *op3_p = NULL_TREE;
kono
parents:
diff changeset
556 }
kono
parents:
diff changeset
557 else
kono
parents:
diff changeset
558 gcc_unreachable ();
kono
parents:
diff changeset
559 }
kono
parents:
diff changeset
560
kono
parents:
diff changeset
561 /* Extract operands for a GIMPLE_COND statement out of COND_EXPR tree COND. */
kono
parents:
diff changeset
562
kono
parents:
diff changeset
563 void
kono
parents:
diff changeset
564 gimple_cond_get_ops_from_tree (tree cond, enum tree_code *code_p,
kono
parents:
diff changeset
565 tree *lhs_p, tree *rhs_p)
kono
parents:
diff changeset
566 {
kono
parents:
diff changeset
567 gcc_assert (COMPARISON_CLASS_P (cond)
kono
parents:
diff changeset
568 || TREE_CODE (cond) == TRUTH_NOT_EXPR
kono
parents:
diff changeset
569 || is_gimple_min_invariant (cond)
kono
parents:
diff changeset
570 || SSA_VAR_P (cond));
kono
parents:
diff changeset
571
kono
parents:
diff changeset
572 extract_ops_from_tree (cond, code_p, lhs_p, rhs_p);
kono
parents:
diff changeset
573
kono
parents:
diff changeset
574 /* Canonicalize conditionals of the form 'if (!VAL)'. */
kono
parents:
diff changeset
575 if (*code_p == TRUTH_NOT_EXPR)
kono
parents:
diff changeset
576 {
kono
parents:
diff changeset
577 *code_p = EQ_EXPR;
kono
parents:
diff changeset
578 gcc_assert (*lhs_p && *rhs_p == NULL_TREE);
kono
parents:
diff changeset
579 *rhs_p = build_zero_cst (TREE_TYPE (*lhs_p));
kono
parents:
diff changeset
580 }
kono
parents:
diff changeset
581 /* Canonicalize conditionals of the form 'if (VAL)' */
kono
parents:
diff changeset
582 else if (TREE_CODE_CLASS (*code_p) != tcc_comparison)
kono
parents:
diff changeset
583 {
kono
parents:
diff changeset
584 *code_p = NE_EXPR;
kono
parents:
diff changeset
585 gcc_assert (*lhs_p && *rhs_p == NULL_TREE);
kono
parents:
diff changeset
586 *rhs_p = build_zero_cst (TREE_TYPE (*lhs_p));
kono
parents:
diff changeset
587 }
kono
parents:
diff changeset
588 }
kono
parents:
diff changeset
589
kono
parents:
diff changeset
590 /* Return true if T is a valid LHS for a GIMPLE assignment expression. */
kono
parents:
diff changeset
591
kono
parents:
diff changeset
592 bool
kono
parents:
diff changeset
593 is_gimple_lvalue (tree t)
kono
parents:
diff changeset
594 {
kono
parents:
diff changeset
595 return (is_gimple_addressable (t)
kono
parents:
diff changeset
596 || TREE_CODE (t) == WITH_SIZE_EXPR
kono
parents:
diff changeset
597 /* These are complex lvalues, but don't have addresses, so they
kono
parents:
diff changeset
598 go here. */
kono
parents:
diff changeset
599 || TREE_CODE (t) == BIT_FIELD_REF);
kono
parents:
diff changeset
600 }
kono
parents:
diff changeset
601
kono
parents:
diff changeset
602 /* Return true if T is a GIMPLE condition. */
kono
parents:
diff changeset
603
kono
parents:
diff changeset
604 bool
kono
parents:
diff changeset
605 is_gimple_condexpr (tree t)
kono
parents:
diff changeset
606 {
kono
parents:
diff changeset
607 return (is_gimple_val (t) || (COMPARISON_CLASS_P (t)
kono
parents:
diff changeset
608 && !tree_could_throw_p (t)
kono
parents:
diff changeset
609 && is_gimple_val (TREE_OPERAND (t, 0))
kono
parents:
diff changeset
610 && is_gimple_val (TREE_OPERAND (t, 1))));
kono
parents:
diff changeset
611 }
kono
parents:
diff changeset
612
kono
parents:
diff changeset
613 /* Return true if T is a gimple address. */
kono
parents:
diff changeset
614
kono
parents:
diff changeset
615 bool
kono
parents:
diff changeset
616 is_gimple_address (const_tree t)
kono
parents:
diff changeset
617 {
kono
parents:
diff changeset
618 tree op;
kono
parents:
diff changeset
619
kono
parents:
diff changeset
620 if (TREE_CODE (t) != ADDR_EXPR)
kono
parents:
diff changeset
621 return false;
kono
parents:
diff changeset
622
kono
parents:
diff changeset
623 op = TREE_OPERAND (t, 0);
kono
parents:
diff changeset
624 while (handled_component_p (op))
kono
parents:
diff changeset
625 {
kono
parents:
diff changeset
626 if ((TREE_CODE (op) == ARRAY_REF
kono
parents:
diff changeset
627 || TREE_CODE (op) == ARRAY_RANGE_REF)
kono
parents:
diff changeset
628 && !is_gimple_val (TREE_OPERAND (op, 1)))
kono
parents:
diff changeset
629 return false;
kono
parents:
diff changeset
630
kono
parents:
diff changeset
631 op = TREE_OPERAND (op, 0);
kono
parents:
diff changeset
632 }
kono
parents:
diff changeset
633
kono
parents:
diff changeset
634 if (CONSTANT_CLASS_P (op) || TREE_CODE (op) == MEM_REF)
kono
parents:
diff changeset
635 return true;
kono
parents:
diff changeset
636
kono
parents:
diff changeset
637 switch (TREE_CODE (op))
kono
parents:
diff changeset
638 {
kono
parents:
diff changeset
639 case PARM_DECL:
kono
parents:
diff changeset
640 case RESULT_DECL:
kono
parents:
diff changeset
641 case LABEL_DECL:
kono
parents:
diff changeset
642 case FUNCTION_DECL:
kono
parents:
diff changeset
643 case VAR_DECL:
kono
parents:
diff changeset
644 case CONST_DECL:
kono
parents:
diff changeset
645 return true;
kono
parents:
diff changeset
646
kono
parents:
diff changeset
647 default:
kono
parents:
diff changeset
648 return false;
kono
parents:
diff changeset
649 }
kono
parents:
diff changeset
650 }
kono
parents:
diff changeset
651
kono
parents:
diff changeset
652 /* Return true if T is a gimple invariant address. */
kono
parents:
diff changeset
653
kono
parents:
diff changeset
654 bool
kono
parents:
diff changeset
655 is_gimple_invariant_address (const_tree t)
kono
parents:
diff changeset
656 {
kono
parents:
diff changeset
657 const_tree op;
kono
parents:
diff changeset
658
kono
parents:
diff changeset
659 if (TREE_CODE (t) != ADDR_EXPR)
kono
parents:
diff changeset
660 return false;
kono
parents:
diff changeset
661
kono
parents:
diff changeset
662 op = strip_invariant_refs (TREE_OPERAND (t, 0));
kono
parents:
diff changeset
663 if (!op)
kono
parents:
diff changeset
664 return false;
kono
parents:
diff changeset
665
kono
parents:
diff changeset
666 if (TREE_CODE (op) == MEM_REF)
kono
parents:
diff changeset
667 {
kono
parents:
diff changeset
668 const_tree op0 = TREE_OPERAND (op, 0);
kono
parents:
diff changeset
669 return (TREE_CODE (op0) == ADDR_EXPR
kono
parents:
diff changeset
670 && (CONSTANT_CLASS_P (TREE_OPERAND (op0, 0))
kono
parents:
diff changeset
671 || decl_address_invariant_p (TREE_OPERAND (op0, 0))));
kono
parents:
diff changeset
672 }
kono
parents:
diff changeset
673
kono
parents:
diff changeset
674 return CONSTANT_CLASS_P (op) || decl_address_invariant_p (op);
kono
parents:
diff changeset
675 }
kono
parents:
diff changeset
676
kono
parents:
diff changeset
677 /* Return true if T is a gimple invariant address at IPA level
kono
parents:
diff changeset
678 (so addresses of variables on stack are not allowed). */
kono
parents:
diff changeset
679
kono
parents:
diff changeset
680 bool
kono
parents:
diff changeset
681 is_gimple_ip_invariant_address (const_tree t)
kono
parents:
diff changeset
682 {
kono
parents:
diff changeset
683 const_tree op;
kono
parents:
diff changeset
684
kono
parents:
diff changeset
685 if (TREE_CODE (t) != ADDR_EXPR)
kono
parents:
diff changeset
686 return false;
kono
parents:
diff changeset
687
kono
parents:
diff changeset
688 op = strip_invariant_refs (TREE_OPERAND (t, 0));
kono
parents:
diff changeset
689 if (!op)
kono
parents:
diff changeset
690 return false;
kono
parents:
diff changeset
691
kono
parents:
diff changeset
692 if (TREE_CODE (op) == MEM_REF)
kono
parents:
diff changeset
693 {
kono
parents:
diff changeset
694 const_tree op0 = TREE_OPERAND (op, 0);
kono
parents:
diff changeset
695 return (TREE_CODE (op0) == ADDR_EXPR
kono
parents:
diff changeset
696 && (CONSTANT_CLASS_P (TREE_OPERAND (op0, 0))
kono
parents:
diff changeset
697 || decl_address_ip_invariant_p (TREE_OPERAND (op0, 0))));
kono
parents:
diff changeset
698 }
kono
parents:
diff changeset
699
kono
parents:
diff changeset
700 return CONSTANT_CLASS_P (op) || decl_address_ip_invariant_p (op);
kono
parents:
diff changeset
701 }
kono
parents:
diff changeset
702
kono
parents:
diff changeset
703 /* Return true if T is a GIMPLE minimal invariant. It's a restricted
kono
parents:
diff changeset
704 form of function invariant. */
kono
parents:
diff changeset
705
kono
parents:
diff changeset
706 bool
kono
parents:
diff changeset
707 is_gimple_min_invariant (const_tree t)
kono
parents:
diff changeset
708 {
kono
parents:
diff changeset
709 if (TREE_CODE (t) == ADDR_EXPR)
kono
parents:
diff changeset
710 return is_gimple_invariant_address (t);
kono
parents:
diff changeset
711
kono
parents:
diff changeset
712 return is_gimple_constant (t);
kono
parents:
diff changeset
713 }
kono
parents:
diff changeset
714
kono
parents:
diff changeset
715 /* Return true if T is a GIMPLE interprocedural invariant. It's a restricted
kono
parents:
diff changeset
716 form of gimple minimal invariant. */
kono
parents:
diff changeset
717
kono
parents:
diff changeset
718 bool
kono
parents:
diff changeset
719 is_gimple_ip_invariant (const_tree t)
kono
parents:
diff changeset
720 {
kono
parents:
diff changeset
721 if (TREE_CODE (t) == ADDR_EXPR)
kono
parents:
diff changeset
722 return is_gimple_ip_invariant_address (t);
kono
parents:
diff changeset
723
kono
parents:
diff changeset
724 return is_gimple_constant (t);
kono
parents:
diff changeset
725 }
kono
parents:
diff changeset
726
kono
parents:
diff changeset
727 /* Return true if T is a non-aggregate register variable. */
kono
parents:
diff changeset
728
kono
parents:
diff changeset
729 bool
kono
parents:
diff changeset
730 is_gimple_reg (tree t)
kono
parents:
diff changeset
731 {
kono
parents:
diff changeset
732 if (virtual_operand_p (t))
kono
parents:
diff changeset
733 return false;
kono
parents:
diff changeset
734
kono
parents:
diff changeset
735 if (TREE_CODE (t) == SSA_NAME)
kono
parents:
diff changeset
736 return true;
kono
parents:
diff changeset
737
kono
parents:
diff changeset
738 if (!is_gimple_variable (t))
kono
parents:
diff changeset
739 return false;
kono
parents:
diff changeset
740
kono
parents:
diff changeset
741 if (!is_gimple_reg_type (TREE_TYPE (t)))
kono
parents:
diff changeset
742 return false;
kono
parents:
diff changeset
743
kono
parents:
diff changeset
744 /* A volatile decl is not acceptable because we can't reuse it as
kono
parents:
diff changeset
745 needed. We need to copy it into a temp first. */
kono
parents:
diff changeset
746 if (TREE_THIS_VOLATILE (t))
kono
parents:
diff changeset
747 return false;
kono
parents:
diff changeset
748
kono
parents:
diff changeset
749 /* We define "registers" as things that can be renamed as needed,
kono
parents:
diff changeset
750 which with our infrastructure does not apply to memory. */
kono
parents:
diff changeset
751 if (needs_to_live_in_memory (t))
kono
parents:
diff changeset
752 return false;
kono
parents:
diff changeset
753
kono
parents:
diff changeset
754 /* Hard register variables are an interesting case. For those that
kono
parents:
diff changeset
755 are call-clobbered, we don't know where all the calls are, since
kono
parents:
diff changeset
756 we don't (want to) take into account which operations will turn
kono
parents:
diff changeset
757 into libcalls at the rtl level. For those that are call-saved,
kono
parents:
diff changeset
758 we don't currently model the fact that calls may in fact change
kono
parents:
diff changeset
759 global hard registers, nor do we examine ASM_CLOBBERS at the tree
kono
parents:
diff changeset
760 level, and so miss variable changes that might imply. All around,
kono
parents:
diff changeset
761 it seems safest to not do too much optimization with these at the
kono
parents:
diff changeset
762 tree level at all. We'll have to rely on the rtl optimizers to
kono
parents:
diff changeset
763 clean this up, as there we've got all the appropriate bits exposed. */
kono
parents:
diff changeset
764 if (TREE_CODE (t) == VAR_DECL && DECL_HARD_REGISTER (t))
kono
parents:
diff changeset
765 return false;
kono
parents:
diff changeset
766
kono
parents:
diff changeset
767 /* Complex and vector values must have been put into SSA-like form.
kono
parents:
diff changeset
768 That is, no assignments to the individual components. */
kono
parents:
diff changeset
769 if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE
kono
parents:
diff changeset
770 || TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
kono
parents:
diff changeset
771 return DECL_GIMPLE_REG_P (t);
kono
parents:
diff changeset
772
kono
parents:
diff changeset
773 return true;
kono
parents:
diff changeset
774 }
kono
parents:
diff changeset
775
kono
parents:
diff changeset
776
kono
parents:
diff changeset
777 /* Return true if T is a GIMPLE rvalue, i.e. an identifier or a constant. */
kono
parents:
diff changeset
778
kono
parents:
diff changeset
779 bool
kono
parents:
diff changeset
780 is_gimple_val (tree t)
kono
parents:
diff changeset
781 {
kono
parents:
diff changeset
782 /* Make loads from volatiles and memory vars explicit. */
kono
parents:
diff changeset
783 if (is_gimple_variable (t)
kono
parents:
diff changeset
784 && is_gimple_reg_type (TREE_TYPE (t))
kono
parents:
diff changeset
785 && !is_gimple_reg (t))
kono
parents:
diff changeset
786 return false;
kono
parents:
diff changeset
787
kono
parents:
diff changeset
788 return (is_gimple_variable (t) || is_gimple_min_invariant (t));
kono
parents:
diff changeset
789 }
kono
parents:
diff changeset
790
kono
parents:
diff changeset
791 /* Similarly, but accept hard registers as inputs to asm statements. */
kono
parents:
diff changeset
792
kono
parents:
diff changeset
793 bool
kono
parents:
diff changeset
794 is_gimple_asm_val (tree t)
kono
parents:
diff changeset
795 {
kono
parents:
diff changeset
796 if (TREE_CODE (t) == VAR_DECL && DECL_HARD_REGISTER (t))
kono
parents:
diff changeset
797 return true;
kono
parents:
diff changeset
798
kono
parents:
diff changeset
799 return is_gimple_val (t);
kono
parents:
diff changeset
800 }
kono
parents:
diff changeset
801
kono
parents:
diff changeset
802 /* Return true if T is a GIMPLE minimal lvalue. */
kono
parents:
diff changeset
803
kono
parents:
diff changeset
804 bool
kono
parents:
diff changeset
805 is_gimple_min_lval (tree t)
kono
parents:
diff changeset
806 {
kono
parents:
diff changeset
807 if (!(t = CONST_CAST_TREE (strip_invariant_refs (t))))
kono
parents:
diff changeset
808 return false;
kono
parents:
diff changeset
809 return (is_gimple_id (t) || TREE_CODE (t) == MEM_REF);
kono
parents:
diff changeset
810 }
kono
parents:
diff changeset
811
kono
parents:
diff changeset
812 /* Return true if T is a valid function operand of a CALL_EXPR. */
kono
parents:
diff changeset
813
kono
parents:
diff changeset
814 bool
kono
parents:
diff changeset
815 is_gimple_call_addr (tree t)
kono
parents:
diff changeset
816 {
kono
parents:
diff changeset
817 return (TREE_CODE (t) == OBJ_TYPE_REF || is_gimple_val (t));
kono
parents:
diff changeset
818 }
kono
parents:
diff changeset
819
kono
parents:
diff changeset
820 /* Return true if T is a valid address operand of a MEM_REF. */
kono
parents:
diff changeset
821
kono
parents:
diff changeset
822 bool
kono
parents:
diff changeset
823 is_gimple_mem_ref_addr (tree t)
kono
parents:
diff changeset
824 {
kono
parents:
diff changeset
825 return (is_gimple_reg (t)
kono
parents:
diff changeset
826 || TREE_CODE (t) == INTEGER_CST
kono
parents:
diff changeset
827 || (TREE_CODE (t) == ADDR_EXPR
kono
parents:
diff changeset
828 && (CONSTANT_CLASS_P (TREE_OPERAND (t, 0))
kono
parents:
diff changeset
829 || decl_address_invariant_p (TREE_OPERAND (t, 0)))));
kono
parents:
diff changeset
830 }
kono
parents:
diff changeset
831
kono
parents:
diff changeset
832 /* Hold trees marked addressable during expand. */
kono
parents:
diff changeset
833
kono
parents:
diff changeset
834 static hash_set<tree> *mark_addressable_queue;
kono
parents:
diff changeset
835
kono
parents:
diff changeset
836 /* Mark X as addressable or queue it up if called during expand. We
kono
parents:
diff changeset
837 don't want to apply it immediately during expand because decls are
kono
parents:
diff changeset
838 made addressable at that point due to RTL-only concerns, such as
kono
parents:
diff changeset
839 uses of memcpy for block moves, and TREE_ADDRESSABLE changes
kono
parents:
diff changeset
840 is_gimple_reg, which might make it seem like a variable that used
kono
parents:
diff changeset
841 to be a gimple_reg shouldn't have been an SSA name. So we queue up
kono
parents:
diff changeset
842 this flag setting and only apply it when we're done with GIMPLE and
kono
parents:
diff changeset
843 only RTL issues matter. */
kono
parents:
diff changeset
844
kono
parents:
diff changeset
845 static void
kono
parents:
diff changeset
846 mark_addressable_1 (tree x)
kono
parents:
diff changeset
847 {
kono
parents:
diff changeset
848 if (!currently_expanding_to_rtl)
kono
parents:
diff changeset
849 {
kono
parents:
diff changeset
850 TREE_ADDRESSABLE (x) = 1;
kono
parents:
diff changeset
851 return;
kono
parents:
diff changeset
852 }
kono
parents:
diff changeset
853
kono
parents:
diff changeset
854 if (!mark_addressable_queue)
kono
parents:
diff changeset
855 mark_addressable_queue = new hash_set<tree>();
kono
parents:
diff changeset
856 mark_addressable_queue->add (x);
kono
parents:
diff changeset
857 }
kono
parents:
diff changeset
858
kono
parents:
diff changeset
859 /* Adaptor for mark_addressable_1 for use in hash_set traversal. */
kono
parents:
diff changeset
860
kono
parents:
diff changeset
861 bool
kono
parents:
diff changeset
862 mark_addressable_2 (tree const &x, void * ATTRIBUTE_UNUSED = NULL)
kono
parents:
diff changeset
863 {
kono
parents:
diff changeset
864 mark_addressable_1 (x);
kono
parents:
diff changeset
865 return false;
kono
parents:
diff changeset
866 }
kono
parents:
diff changeset
867
kono
parents:
diff changeset
868 /* Mark all queued trees as addressable, and empty the queue. To be
kono
parents:
diff changeset
869 called right after clearing CURRENTLY_EXPANDING_TO_RTL. */
kono
parents:
diff changeset
870
kono
parents:
diff changeset
871 void
kono
parents:
diff changeset
872 flush_mark_addressable_queue ()
kono
parents:
diff changeset
873 {
kono
parents:
diff changeset
874 gcc_assert (!currently_expanding_to_rtl);
kono
parents:
diff changeset
875 if (mark_addressable_queue)
kono
parents:
diff changeset
876 {
kono
parents:
diff changeset
877 mark_addressable_queue->traverse<void*, mark_addressable_2> (NULL);
kono
parents:
diff changeset
878 delete mark_addressable_queue;
kono
parents:
diff changeset
879 mark_addressable_queue = NULL;
kono
parents:
diff changeset
880 }
kono
parents:
diff changeset
881 }
kono
parents:
diff changeset
882
kono
parents:
diff changeset
883 /* Mark X addressable. Unlike the langhook we expect X to be in gimple
kono
parents:
diff changeset
884 form and we don't do any syntax checking. */
kono
parents:
diff changeset
885
kono
parents:
diff changeset
886 void
kono
parents:
diff changeset
887 mark_addressable (tree x)
kono
parents:
diff changeset
888 {
kono
parents:
diff changeset
889 while (handled_component_p (x))
kono
parents:
diff changeset
890 x = TREE_OPERAND (x, 0);
kono
parents:
diff changeset
891 if (TREE_CODE (x) == MEM_REF
kono
parents:
diff changeset
892 && TREE_CODE (TREE_OPERAND (x, 0)) == ADDR_EXPR)
kono
parents:
diff changeset
893 x = TREE_OPERAND (TREE_OPERAND (x, 0), 0);
kono
parents:
diff changeset
894 if (!VAR_P (x)
kono
parents:
diff changeset
895 && TREE_CODE (x) != PARM_DECL
kono
parents:
diff changeset
896 && TREE_CODE (x) != RESULT_DECL)
kono
parents:
diff changeset
897 return;
kono
parents:
diff changeset
898 mark_addressable_1 (x);
kono
parents:
diff changeset
899
kono
parents:
diff changeset
900 /* Also mark the artificial SSA_NAME that points to the partition of X. */
kono
parents:
diff changeset
901 if (TREE_CODE (x) == VAR_DECL
kono
parents:
diff changeset
902 && !DECL_EXTERNAL (x)
kono
parents:
diff changeset
903 && !TREE_STATIC (x)
kono
parents:
diff changeset
904 && cfun->gimple_df != NULL
kono
parents:
diff changeset
905 && cfun->gimple_df->decls_to_pointers != NULL)
kono
parents:
diff changeset
906 {
kono
parents:
diff changeset
907 tree *namep = cfun->gimple_df->decls_to_pointers->get (x);
kono
parents:
diff changeset
908 if (namep)
kono
parents:
diff changeset
909 mark_addressable_1 (*namep);
kono
parents:
diff changeset
910 }
kono
parents:
diff changeset
911 }
kono
parents:
diff changeset
912
kono
parents:
diff changeset
913 /* Returns true iff T is a valid RHS for an assignment to a renamed
kono
parents:
diff changeset
914 user -- or front-end generated artificial -- variable. */
kono
parents:
diff changeset
915
kono
parents:
diff changeset
916 bool
kono
parents:
diff changeset
917 is_gimple_reg_rhs (tree t)
kono
parents:
diff changeset
918 {
kono
parents:
diff changeset
919 return get_gimple_rhs_class (TREE_CODE (t)) != GIMPLE_INVALID_RHS;
kono
parents:
diff changeset
920 }
kono
parents:
diff changeset
921
kono
parents:
diff changeset
922 #include "gt-gimple-expr.h"