annotate gcc/ipa-polymorphic-call.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 /* Analysis of polymorphic call context.
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2 Copyright (C) 2013-2018 Free Software Foundation, Inc.
111
kono
parents:
diff changeset
3 Contributed by Jan Hubicka
kono
parents:
diff changeset
4
kono
parents:
diff changeset
5 This file is part of GCC.
kono
parents:
diff changeset
6
kono
parents:
diff changeset
7 GCC is free software; you can redistribute it and/or modify it under
kono
parents:
diff changeset
8 the terms of the GNU General Public License as published by the Free
kono
parents:
diff changeset
9 Software Foundation; either version 3, or (at your option) any later
kono
parents:
diff changeset
10 version.
kono
parents:
diff changeset
11
kono
parents:
diff changeset
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
kono
parents:
diff changeset
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
kono
parents:
diff changeset
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
kono
parents:
diff changeset
15 for more details.
kono
parents:
diff changeset
16
kono
parents:
diff changeset
17 You should have received a copy of the GNU General Public License
kono
parents:
diff changeset
18 along with GCC; see the file COPYING3. If not see
kono
parents:
diff changeset
19 <http://www.gnu.org/licenses/>. */
kono
parents:
diff changeset
20
kono
parents:
diff changeset
21 #include "config.h"
kono
parents:
diff changeset
22 #include "system.h"
kono
parents:
diff changeset
23 #include "coretypes.h"
kono
parents:
diff changeset
24 #include "backend.h"
kono
parents:
diff changeset
25 #include "rtl.h"
kono
parents:
diff changeset
26 #include "tree.h"
kono
parents:
diff changeset
27 #include "gimple.h"
kono
parents:
diff changeset
28 #include "tree-pass.h"
kono
parents:
diff changeset
29 #include "tree-ssa-operands.h"
kono
parents:
diff changeset
30 #include "streamer-hooks.h"
kono
parents:
diff changeset
31 #include "cgraph.h"
kono
parents:
diff changeset
32 #include "data-streamer.h"
kono
parents:
diff changeset
33 #include "diagnostic.h"
kono
parents:
diff changeset
34 #include "alias.h"
kono
parents:
diff changeset
35 #include "fold-const.h"
kono
parents:
diff changeset
36 #include "calls.h"
kono
parents:
diff changeset
37 #include "ipa-utils.h"
kono
parents:
diff changeset
38 #include "tree-dfa.h"
kono
parents:
diff changeset
39 #include "gimple-pretty-print.h"
kono
parents:
diff changeset
40 #include "tree-into-ssa.h"
kono
parents:
diff changeset
41 #include "params.h"
kono
parents:
diff changeset
42
kono
parents:
diff changeset
43 /* Return true when TYPE contains an polymorphic type and thus is interesting
kono
parents:
diff changeset
44 for devirtualization machinery. */
kono
parents:
diff changeset
45
kono
parents:
diff changeset
46 static bool contains_type_p (tree, HOST_WIDE_INT, tree,
kono
parents:
diff changeset
47 bool consider_placement_new = true,
kono
parents:
diff changeset
48 bool consider_bases = true);
kono
parents:
diff changeset
49
kono
parents:
diff changeset
50 bool
kono
parents:
diff changeset
51 contains_polymorphic_type_p (const_tree type)
kono
parents:
diff changeset
52 {
kono
parents:
diff changeset
53 type = TYPE_MAIN_VARIANT (type);
kono
parents:
diff changeset
54
kono
parents:
diff changeset
55 if (RECORD_OR_UNION_TYPE_P (type))
kono
parents:
diff changeset
56 {
kono
parents:
diff changeset
57 if (TYPE_BINFO (type)
kono
parents:
diff changeset
58 && polymorphic_type_binfo_p (TYPE_BINFO (type)))
kono
parents:
diff changeset
59 return true;
kono
parents:
diff changeset
60 for (tree fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
kono
parents:
diff changeset
61 if (TREE_CODE (fld) == FIELD_DECL
kono
parents:
diff changeset
62 && !DECL_ARTIFICIAL (fld)
kono
parents:
diff changeset
63 && contains_polymorphic_type_p (TREE_TYPE (fld)))
kono
parents:
diff changeset
64 return true;
kono
parents:
diff changeset
65 return false;
kono
parents:
diff changeset
66 }
kono
parents:
diff changeset
67 if (TREE_CODE (type) == ARRAY_TYPE)
kono
parents:
diff changeset
68 return contains_polymorphic_type_p (TREE_TYPE (type));
kono
parents:
diff changeset
69 return false;
kono
parents:
diff changeset
70 }
kono
parents:
diff changeset
71
kono
parents:
diff changeset
72 /* Return true if it seems valid to use placement new to build EXPECTED_TYPE
kono
parents:
diff changeset
73 at possition CUR_OFFSET within TYPE.
kono
parents:
diff changeset
74
kono
parents:
diff changeset
75 POD can be changed to an instance of a polymorphic type by
kono
parents:
diff changeset
76 placement new. Here we play safe and assume that any
kono
parents:
diff changeset
77 non-polymorphic type is POD. */
kono
parents:
diff changeset
78 bool
kono
parents:
diff changeset
79 possible_placement_new (tree type, tree expected_type,
kono
parents:
diff changeset
80 HOST_WIDE_INT cur_offset)
kono
parents:
diff changeset
81 {
kono
parents:
diff changeset
82 if (cur_offset < 0)
kono
parents:
diff changeset
83 return true;
kono
parents:
diff changeset
84 return ((TREE_CODE (type) != RECORD_TYPE
kono
parents:
diff changeset
85 || !TYPE_BINFO (type)
kono
parents:
diff changeset
86 || cur_offset >= POINTER_SIZE
kono
parents:
diff changeset
87 || !polymorphic_type_binfo_p (TYPE_BINFO (type)))
kono
parents:
diff changeset
88 && (!TYPE_SIZE (type)
kono
parents:
diff changeset
89 || !tree_fits_shwi_p (TYPE_SIZE (type))
kono
parents:
diff changeset
90 || (cur_offset
kono
parents:
diff changeset
91 + (expected_type ? tree_to_uhwi (TYPE_SIZE (expected_type))
kono
parents:
diff changeset
92 : POINTER_SIZE)
kono
parents:
diff changeset
93 <= tree_to_uhwi (TYPE_SIZE (type)))));
kono
parents:
diff changeset
94 }
kono
parents:
diff changeset
95
kono
parents:
diff changeset
96 /* THIS->OUTER_TYPE is a type of memory object where object of OTR_TYPE
kono
parents:
diff changeset
97 is contained at THIS->OFFSET. Walk the memory representation of
kono
parents:
diff changeset
98 THIS->OUTER_TYPE and find the outermost class type that match
kono
parents:
diff changeset
99 OTR_TYPE or contain OTR_TYPE as a base. Update THIS
kono
parents:
diff changeset
100 to represent it.
kono
parents:
diff changeset
101
kono
parents:
diff changeset
102 If OTR_TYPE is NULL, just find outermost polymorphic type with
kono
parents:
diff changeset
103 virtual table present at possition OFFSET.
kono
parents:
diff changeset
104
kono
parents:
diff changeset
105 For example when THIS represents type
kono
parents:
diff changeset
106 class A
kono
parents:
diff changeset
107 {
kono
parents:
diff changeset
108 int a;
kono
parents:
diff changeset
109 class B b;
kono
parents:
diff changeset
110 }
kono
parents:
diff changeset
111 and we look for type at offset sizeof(int), we end up with B and offset 0.
kono
parents:
diff changeset
112 If the same is produced by multiple inheritance, we end up with A and offset
kono
parents:
diff changeset
113 sizeof(int).
kono
parents:
diff changeset
114
kono
parents:
diff changeset
115 If we can not find corresponding class, give up by setting
kono
parents:
diff changeset
116 THIS->OUTER_TYPE to OTR_TYPE and THIS->OFFSET to NULL.
kono
parents:
diff changeset
117 Return true when lookup was sucesful.
kono
parents:
diff changeset
118
kono
parents:
diff changeset
119 When CONSIDER_PLACEMENT_NEW is false, reject contexts that may be made
kono
parents:
diff changeset
120 valid only via allocation of new polymorphic type inside by means
kono
parents:
diff changeset
121 of placement new.
kono
parents:
diff changeset
122
kono
parents:
diff changeset
123 When CONSIDER_BASES is false, only look for actual fields, not base types
kono
parents:
diff changeset
124 of TYPE. */
kono
parents:
diff changeset
125
kono
parents:
diff changeset
126 bool
kono
parents:
diff changeset
127 ipa_polymorphic_call_context::restrict_to_inner_class (tree otr_type,
kono
parents:
diff changeset
128 bool consider_placement_new,
kono
parents:
diff changeset
129 bool consider_bases)
kono
parents:
diff changeset
130 {
kono
parents:
diff changeset
131 tree type = outer_type;
kono
parents:
diff changeset
132 HOST_WIDE_INT cur_offset = offset;
kono
parents:
diff changeset
133 bool speculative = false;
kono
parents:
diff changeset
134 bool size_unknown = false;
kono
parents:
diff changeset
135 unsigned HOST_WIDE_INT otr_type_size = POINTER_SIZE;
kono
parents:
diff changeset
136
kono
parents:
diff changeset
137 /* Update OUTER_TYPE to match EXPECTED_TYPE if it is not set. */
kono
parents:
diff changeset
138 if (!outer_type)
kono
parents:
diff changeset
139 {
kono
parents:
diff changeset
140 clear_outer_type (otr_type);
kono
parents:
diff changeset
141 type = otr_type;
kono
parents:
diff changeset
142 cur_offset = 0;
kono
parents:
diff changeset
143 }
kono
parents:
diff changeset
144 /* See if OFFSET points inside OUTER_TYPE. If it does not, we know
kono
parents:
diff changeset
145 that the context is either invalid, or the instance type must be
kono
parents:
diff changeset
146 derived from OUTER_TYPE.
kono
parents:
diff changeset
147
kono
parents:
diff changeset
148 Because the instance type may contain field whose type is of OUTER_TYPE,
kono
parents:
diff changeset
149 we can not derive any effective information about it.
kono
parents:
diff changeset
150
kono
parents:
diff changeset
151 TODO: In the case we know all derrived types, we can definitely do better
kono
parents:
diff changeset
152 here. */
kono
parents:
diff changeset
153 else if (TYPE_SIZE (outer_type)
kono
parents:
diff changeset
154 && tree_fits_shwi_p (TYPE_SIZE (outer_type))
kono
parents:
diff changeset
155 && tree_to_shwi (TYPE_SIZE (outer_type)) >= 0
kono
parents:
diff changeset
156 && tree_to_shwi (TYPE_SIZE (outer_type)) <= offset)
kono
parents:
diff changeset
157 {
kono
parents:
diff changeset
158 bool der = maybe_derived_type; /* clear_outer_type will reset it. */
kono
parents:
diff changeset
159 bool dyn = dynamic;
kono
parents:
diff changeset
160 clear_outer_type (otr_type);
kono
parents:
diff changeset
161 type = otr_type;
kono
parents:
diff changeset
162 cur_offset = 0;
kono
parents:
diff changeset
163
kono
parents:
diff changeset
164 /* If derived type is not allowed, we know that the context is invalid.
kono
parents:
diff changeset
165 For dynamic types, we really do not have information about
kono
parents:
diff changeset
166 size of the memory location. It is possible that completely
kono
parents:
diff changeset
167 different type is stored after outer_type. */
kono
parents:
diff changeset
168 if (!der && !dyn)
kono
parents:
diff changeset
169 {
kono
parents:
diff changeset
170 clear_speculation ();
kono
parents:
diff changeset
171 invalid = true;
kono
parents:
diff changeset
172 return false;
kono
parents:
diff changeset
173 }
kono
parents:
diff changeset
174 }
kono
parents:
diff changeset
175
kono
parents:
diff changeset
176 if (otr_type && TYPE_SIZE (otr_type)
kono
parents:
diff changeset
177 && tree_fits_shwi_p (TYPE_SIZE (otr_type)))
kono
parents:
diff changeset
178 otr_type_size = tree_to_uhwi (TYPE_SIZE (otr_type));
kono
parents:
diff changeset
179
kono
parents:
diff changeset
180 if (!type || offset < 0)
kono
parents:
diff changeset
181 goto no_useful_type_info;
kono
parents:
diff changeset
182
kono
parents:
diff changeset
183 /* Find the sub-object the constant actually refers to and mark whether it is
kono
parents:
diff changeset
184 an artificial one (as opposed to a user-defined one).
kono
parents:
diff changeset
185
kono
parents:
diff changeset
186 This loop is performed twice; first time for outer_type and second time
kono
parents:
diff changeset
187 for speculative_outer_type. The second run has SPECULATIVE set. */
kono
parents:
diff changeset
188 while (true)
kono
parents:
diff changeset
189 {
kono
parents:
diff changeset
190 unsigned HOST_WIDE_INT pos, size;
kono
parents:
diff changeset
191 tree fld;
kono
parents:
diff changeset
192
kono
parents:
diff changeset
193 /* If we do not know size of TYPE, we need to be more conservative
kono
parents:
diff changeset
194 about accepting cases where we can not find EXPECTED_TYPE.
kono
parents:
diff changeset
195 Generally the types that do matter here are of constant size.
kono
parents:
diff changeset
196 Size_unknown case should be very rare. */
kono
parents:
diff changeset
197 if (TYPE_SIZE (type)
kono
parents:
diff changeset
198 && tree_fits_shwi_p (TYPE_SIZE (type))
kono
parents:
diff changeset
199 && tree_to_shwi (TYPE_SIZE (type)) >= 0)
kono
parents:
diff changeset
200 size_unknown = false;
kono
parents:
diff changeset
201 else
kono
parents:
diff changeset
202 size_unknown = true;
kono
parents:
diff changeset
203
kono
parents:
diff changeset
204 /* On a match, just return what we found. */
kono
parents:
diff changeset
205 if ((otr_type
kono
parents:
diff changeset
206 && types_odr_comparable (type, otr_type)
kono
parents:
diff changeset
207 && types_same_for_odr (type, otr_type))
kono
parents:
diff changeset
208 || (!otr_type
kono
parents:
diff changeset
209 && TREE_CODE (type) == RECORD_TYPE
kono
parents:
diff changeset
210 && TYPE_BINFO (type)
kono
parents:
diff changeset
211 && polymorphic_type_binfo_p (TYPE_BINFO (type))))
kono
parents:
diff changeset
212 {
kono
parents:
diff changeset
213 if (speculative)
kono
parents:
diff changeset
214 {
kono
parents:
diff changeset
215 /* If we did not match the offset, just give up on speculation. */
kono
parents:
diff changeset
216 if (cur_offset != 0
kono
parents:
diff changeset
217 /* Also check if speculation did not end up being same as
kono
parents:
diff changeset
218 non-speculation. */
kono
parents:
diff changeset
219 || (types_must_be_same_for_odr (speculative_outer_type,
kono
parents:
diff changeset
220 outer_type)
kono
parents:
diff changeset
221 && (maybe_derived_type
kono
parents:
diff changeset
222 == speculative_maybe_derived_type)))
kono
parents:
diff changeset
223 clear_speculation ();
kono
parents:
diff changeset
224 return true;
kono
parents:
diff changeset
225 }
kono
parents:
diff changeset
226 else
kono
parents:
diff changeset
227 {
kono
parents:
diff changeset
228 /* If type is known to be final, do not worry about derived
kono
parents:
diff changeset
229 types. Testing it here may help us to avoid speculation. */
kono
parents:
diff changeset
230 if (otr_type && TREE_CODE (outer_type) == RECORD_TYPE
kono
parents:
diff changeset
231 && (!in_lto_p || odr_type_p (outer_type))
kono
parents:
diff changeset
232 && type_with_linkage_p (outer_type)
kono
parents:
diff changeset
233 && type_known_to_have_no_derivations_p (outer_type))
kono
parents:
diff changeset
234 maybe_derived_type = false;
kono
parents:
diff changeset
235
kono
parents:
diff changeset
236 /* Type can not contain itself on an non-zero offset. In that case
kono
parents:
diff changeset
237 just give up. Still accept the case where size is now known.
kono
parents:
diff changeset
238 Either the second copy may appear past the end of type or within
kono
parents:
diff changeset
239 the non-POD buffer located inside the variably sized type
kono
parents:
diff changeset
240 itself. */
kono
parents:
diff changeset
241 if (cur_offset != 0)
kono
parents:
diff changeset
242 goto no_useful_type_info;
kono
parents:
diff changeset
243 /* If we determined type precisely or we have no clue on
kono
parents:
diff changeset
244 speuclation, we are done. */
kono
parents:
diff changeset
245 if (!maybe_derived_type || !speculative_outer_type
kono
parents:
diff changeset
246 || !speculation_consistent_p (speculative_outer_type,
kono
parents:
diff changeset
247 speculative_offset,
kono
parents:
diff changeset
248 speculative_maybe_derived_type,
kono
parents:
diff changeset
249 otr_type))
kono
parents:
diff changeset
250 {
kono
parents:
diff changeset
251 clear_speculation ();
kono
parents:
diff changeset
252 return true;
kono
parents:
diff changeset
253 }
kono
parents:
diff changeset
254 /* Otherwise look into speculation now. */
kono
parents:
diff changeset
255 else
kono
parents:
diff changeset
256 {
kono
parents:
diff changeset
257 speculative = true;
kono
parents:
diff changeset
258 type = speculative_outer_type;
kono
parents:
diff changeset
259 cur_offset = speculative_offset;
kono
parents:
diff changeset
260 continue;
kono
parents:
diff changeset
261 }
kono
parents:
diff changeset
262 }
kono
parents:
diff changeset
263 }
kono
parents:
diff changeset
264
kono
parents:
diff changeset
265 /* Walk fields and find corresponding on at OFFSET. */
kono
parents:
diff changeset
266 if (TREE_CODE (type) == RECORD_TYPE)
kono
parents:
diff changeset
267 {
kono
parents:
diff changeset
268 for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
kono
parents:
diff changeset
269 {
kono
parents:
diff changeset
270 if (TREE_CODE (fld) != FIELD_DECL
kono
parents:
diff changeset
271 || TREE_TYPE (fld) == error_mark_node)
kono
parents:
diff changeset
272 continue;
kono
parents:
diff changeset
273
kono
parents:
diff changeset
274 pos = int_bit_position (fld);
kono
parents:
diff changeset
275 if (pos > (unsigned HOST_WIDE_INT)cur_offset)
kono
parents:
diff changeset
276 continue;
kono
parents:
diff changeset
277
kono
parents:
diff changeset
278 /* Do not consider vptr itself. Not even for placement new. */
kono
parents:
diff changeset
279 if (!pos && DECL_ARTIFICIAL (fld)
kono
parents:
diff changeset
280 && POINTER_TYPE_P (TREE_TYPE (fld))
kono
parents:
diff changeset
281 && TYPE_BINFO (type)
kono
parents:
diff changeset
282 && polymorphic_type_binfo_p (TYPE_BINFO (type)))
kono
parents:
diff changeset
283 continue;
kono
parents:
diff changeset
284
kono
parents:
diff changeset
285 if (!DECL_SIZE (fld) || !tree_fits_uhwi_p (DECL_SIZE (fld)))
kono
parents:
diff changeset
286 goto no_useful_type_info;
kono
parents:
diff changeset
287 size = tree_to_uhwi (DECL_SIZE (fld));
kono
parents:
diff changeset
288
kono
parents:
diff changeset
289 /* We can always skip types smaller than pointer size:
kono
parents:
diff changeset
290 those can not contain a virtual table pointer.
kono
parents:
diff changeset
291
kono
parents:
diff changeset
292 Disqualifying fields that are too small to fit OTR_TYPE
kono
parents:
diff changeset
293 saves work needed to walk them for no benefit.
kono
parents:
diff changeset
294 Because of the way the bases are packed into a class, the
kono
parents:
diff changeset
295 field's size may be smaller than type size, so it needs
kono
parents:
diff changeset
296 to be done with a care. */
kono
parents:
diff changeset
297
kono
parents:
diff changeset
298 if (pos <= (unsigned HOST_WIDE_INT)cur_offset
kono
parents:
diff changeset
299 && (pos + size) >= (unsigned HOST_WIDE_INT)cur_offset
kono
parents:
diff changeset
300 + POINTER_SIZE
kono
parents:
diff changeset
301 && (!otr_type
kono
parents:
diff changeset
302 || !TYPE_SIZE (TREE_TYPE (fld))
kono
parents:
diff changeset
303 || !tree_fits_shwi_p (TYPE_SIZE (TREE_TYPE (fld)))
kono
parents:
diff changeset
304 || (pos + tree_to_uhwi (TYPE_SIZE (TREE_TYPE (fld))))
kono
parents:
diff changeset
305 >= cur_offset + otr_type_size))
kono
parents:
diff changeset
306 break;
kono
parents:
diff changeset
307 }
kono
parents:
diff changeset
308
kono
parents:
diff changeset
309 if (!fld)
kono
parents:
diff changeset
310 goto no_useful_type_info;
kono
parents:
diff changeset
311
kono
parents:
diff changeset
312 type = TYPE_MAIN_VARIANT (TREE_TYPE (fld));
kono
parents:
diff changeset
313 cur_offset -= pos;
kono
parents:
diff changeset
314 /* DECL_ARTIFICIAL represents a basetype. */
kono
parents:
diff changeset
315 if (!DECL_ARTIFICIAL (fld))
kono
parents:
diff changeset
316 {
kono
parents:
diff changeset
317 if (!speculative)
kono
parents:
diff changeset
318 {
kono
parents:
diff changeset
319 outer_type = type;
kono
parents:
diff changeset
320 offset = cur_offset;
kono
parents:
diff changeset
321 /* As soon as we se an field containing the type,
kono
parents:
diff changeset
322 we know we are not looking for derivations. */
kono
parents:
diff changeset
323 maybe_derived_type = false;
kono
parents:
diff changeset
324 }
kono
parents:
diff changeset
325 else
kono
parents:
diff changeset
326 {
kono
parents:
diff changeset
327 speculative_outer_type = type;
kono
parents:
diff changeset
328 speculative_offset = cur_offset;
kono
parents:
diff changeset
329 speculative_maybe_derived_type = false;
kono
parents:
diff changeset
330 }
kono
parents:
diff changeset
331 }
kono
parents:
diff changeset
332 else if (!consider_bases)
kono
parents:
diff changeset
333 goto no_useful_type_info;
kono
parents:
diff changeset
334 }
kono
parents:
diff changeset
335 else if (TREE_CODE (type) == ARRAY_TYPE)
kono
parents:
diff changeset
336 {
kono
parents:
diff changeset
337 tree subtype = TYPE_MAIN_VARIANT (TREE_TYPE (type));
kono
parents:
diff changeset
338
kono
parents:
diff changeset
339 /* Give up if we don't know array field size.
kono
parents:
diff changeset
340 Also give up on non-polymorphic types as they are used
kono
parents:
diff changeset
341 as buffers for placement new. */
kono
parents:
diff changeset
342 if (!TYPE_SIZE (subtype)
kono
parents:
diff changeset
343 || !tree_fits_shwi_p (TYPE_SIZE (subtype))
kono
parents:
diff changeset
344 || tree_to_shwi (TYPE_SIZE (subtype)) <= 0
kono
parents:
diff changeset
345 || !contains_polymorphic_type_p (subtype))
kono
parents:
diff changeset
346 goto no_useful_type_info;
kono
parents:
diff changeset
347
kono
parents:
diff changeset
348 HOST_WIDE_INT new_offset = cur_offset % tree_to_shwi (TYPE_SIZE (subtype));
kono
parents:
diff changeset
349
kono
parents:
diff changeset
350 /* We may see buffer for placement new. In this case the expected type
kono
parents:
diff changeset
351 can be bigger than the subtype. */
kono
parents:
diff changeset
352 if (TYPE_SIZE (subtype)
kono
parents:
diff changeset
353 && (cur_offset + otr_type_size
kono
parents:
diff changeset
354 > tree_to_uhwi (TYPE_SIZE (subtype))))
kono
parents:
diff changeset
355 goto no_useful_type_info;
kono
parents:
diff changeset
356
kono
parents:
diff changeset
357 cur_offset = new_offset;
kono
parents:
diff changeset
358 type = TYPE_MAIN_VARIANT (subtype);
kono
parents:
diff changeset
359 if (!speculative)
kono
parents:
diff changeset
360 {
kono
parents:
diff changeset
361 outer_type = type;
kono
parents:
diff changeset
362 offset = cur_offset;
kono
parents:
diff changeset
363 maybe_derived_type = false;
kono
parents:
diff changeset
364 }
kono
parents:
diff changeset
365 else
kono
parents:
diff changeset
366 {
kono
parents:
diff changeset
367 speculative_outer_type = type;
kono
parents:
diff changeset
368 speculative_offset = cur_offset;
kono
parents:
diff changeset
369 speculative_maybe_derived_type = false;
kono
parents:
diff changeset
370 }
kono
parents:
diff changeset
371 }
kono
parents:
diff changeset
372 /* Give up on anything else. */
kono
parents:
diff changeset
373 else
kono
parents:
diff changeset
374 {
kono
parents:
diff changeset
375 no_useful_type_info:
kono
parents:
diff changeset
376 if (maybe_derived_type && !speculative
kono
parents:
diff changeset
377 && TREE_CODE (outer_type) == RECORD_TYPE
kono
parents:
diff changeset
378 && TREE_CODE (otr_type) == RECORD_TYPE
kono
parents:
diff changeset
379 && TYPE_BINFO (otr_type)
kono
parents:
diff changeset
380 && !offset
kono
parents:
diff changeset
381 && get_binfo_at_offset (TYPE_BINFO (otr_type), 0, outer_type))
kono
parents:
diff changeset
382 {
kono
parents:
diff changeset
383 clear_outer_type (otr_type);
kono
parents:
diff changeset
384 if (!speculative_outer_type
kono
parents:
diff changeset
385 || !speculation_consistent_p (speculative_outer_type,
kono
parents:
diff changeset
386 speculative_offset,
kono
parents:
diff changeset
387 speculative_maybe_derived_type,
kono
parents:
diff changeset
388 otr_type))
kono
parents:
diff changeset
389 clear_speculation ();
kono
parents:
diff changeset
390 if (speculative_outer_type)
kono
parents:
diff changeset
391 {
kono
parents:
diff changeset
392 speculative = true;
kono
parents:
diff changeset
393 type = speculative_outer_type;
kono
parents:
diff changeset
394 cur_offset = speculative_offset;
kono
parents:
diff changeset
395 }
kono
parents:
diff changeset
396 else
kono
parents:
diff changeset
397 return true;
kono
parents:
diff changeset
398 }
kono
parents:
diff changeset
399 /* We found no way to embedd EXPECTED_TYPE in TYPE.
kono
parents:
diff changeset
400 We still permit two special cases - placement new and
kono
parents:
diff changeset
401 the case of variadic types containing themselves. */
kono
parents:
diff changeset
402 if (!speculative
kono
parents:
diff changeset
403 && consider_placement_new
kono
parents:
diff changeset
404 && (size_unknown || !type || maybe_derived_type
kono
parents:
diff changeset
405 || possible_placement_new (type, otr_type, cur_offset)))
kono
parents:
diff changeset
406 {
kono
parents:
diff changeset
407 /* In these weird cases we want to accept the context.
kono
parents:
diff changeset
408 In non-speculative run we have no useful outer_type info
kono
parents:
diff changeset
409 (TODO: we may eventually want to record upper bound on the
kono
parents:
diff changeset
410 type size that can be used to prune the walk),
kono
parents:
diff changeset
411 but we still want to consider speculation that may
kono
parents:
diff changeset
412 give useful info. */
kono
parents:
diff changeset
413 if (!speculative)
kono
parents:
diff changeset
414 {
kono
parents:
diff changeset
415 clear_outer_type (otr_type);
kono
parents:
diff changeset
416 if (!speculative_outer_type
kono
parents:
diff changeset
417 || !speculation_consistent_p (speculative_outer_type,
kono
parents:
diff changeset
418 speculative_offset,
kono
parents:
diff changeset
419 speculative_maybe_derived_type,
kono
parents:
diff changeset
420 otr_type))
kono
parents:
diff changeset
421 clear_speculation ();
kono
parents:
diff changeset
422 if (speculative_outer_type)
kono
parents:
diff changeset
423 {
kono
parents:
diff changeset
424 speculative = true;
kono
parents:
diff changeset
425 type = speculative_outer_type;
kono
parents:
diff changeset
426 cur_offset = speculative_offset;
kono
parents:
diff changeset
427 }
kono
parents:
diff changeset
428 else
kono
parents:
diff changeset
429 return true;
kono
parents:
diff changeset
430 }
kono
parents:
diff changeset
431 else
kono
parents:
diff changeset
432 {
kono
parents:
diff changeset
433 clear_speculation ();
kono
parents:
diff changeset
434 return true;
kono
parents:
diff changeset
435 }
kono
parents:
diff changeset
436 }
kono
parents:
diff changeset
437 else
kono
parents:
diff changeset
438 {
kono
parents:
diff changeset
439 clear_speculation ();
kono
parents:
diff changeset
440 if (speculative)
kono
parents:
diff changeset
441 return true;
kono
parents:
diff changeset
442 clear_outer_type (otr_type);
kono
parents:
diff changeset
443 invalid = true;
kono
parents:
diff changeset
444 return false;
kono
parents:
diff changeset
445 }
kono
parents:
diff changeset
446 }
kono
parents:
diff changeset
447 }
kono
parents:
diff changeset
448 }
kono
parents:
diff changeset
449
kono
parents:
diff changeset
450 /* Return true if OUTER_TYPE contains OTR_TYPE at OFFSET.
kono
parents:
diff changeset
451 CONSIDER_PLACEMENT_NEW makes function to accept cases where OTR_TYPE can
kono
parents:
diff changeset
452 be built within OUTER_TYPE by means of placement new. CONSIDER_BASES makes
kono
parents:
diff changeset
453 function to accept cases where OTR_TYPE appears as base of OUTER_TYPE or as
kono
parents:
diff changeset
454 base of one of fields of OUTER_TYPE. */
kono
parents:
diff changeset
455
kono
parents:
diff changeset
456 static bool
kono
parents:
diff changeset
457 contains_type_p (tree outer_type, HOST_WIDE_INT offset,
kono
parents:
diff changeset
458 tree otr_type,
kono
parents:
diff changeset
459 bool consider_placement_new,
kono
parents:
diff changeset
460 bool consider_bases)
kono
parents:
diff changeset
461 {
kono
parents:
diff changeset
462 ipa_polymorphic_call_context context;
kono
parents:
diff changeset
463
kono
parents:
diff changeset
464 /* Check that type is within range. */
kono
parents:
diff changeset
465 if (offset < 0)
kono
parents:
diff changeset
466 return false;
kono
parents:
diff changeset
467
kono
parents:
diff changeset
468 /* PR ipa/71207
kono
parents:
diff changeset
469 As OUTER_TYPE can be a type which has a diamond virtual inheritance,
kono
parents:
diff changeset
470 it's not necessary that INNER_TYPE will fit within OUTER_TYPE with
kono
parents:
diff changeset
471 a given offset. It can happen that INNER_TYPE also contains a base object,
kono
parents:
diff changeset
472 however it would point to the same instance in the OUTER_TYPE. */
kono
parents:
diff changeset
473
kono
parents:
diff changeset
474 context.offset = offset;
kono
parents:
diff changeset
475 context.outer_type = TYPE_MAIN_VARIANT (outer_type);
kono
parents:
diff changeset
476 context.maybe_derived_type = false;
kono
parents:
diff changeset
477 context.dynamic = false;
kono
parents:
diff changeset
478 return context.restrict_to_inner_class (otr_type, consider_placement_new,
kono
parents:
diff changeset
479 consider_bases);
kono
parents:
diff changeset
480 }
kono
parents:
diff changeset
481
kono
parents:
diff changeset
482
kono
parents:
diff changeset
483 /* Return a FUNCTION_DECL if FN represent a constructor or destructor.
kono
parents:
diff changeset
484 If CHECK_CLONES is true, also check for clones of ctor/dtors. */
kono
parents:
diff changeset
485
kono
parents:
diff changeset
486 tree
kono
parents:
diff changeset
487 polymorphic_ctor_dtor_p (tree fn, bool check_clones)
kono
parents:
diff changeset
488 {
kono
parents:
diff changeset
489 if (TREE_CODE (TREE_TYPE (fn)) != METHOD_TYPE
kono
parents:
diff changeset
490 || (!DECL_CXX_CONSTRUCTOR_P (fn) && !DECL_CXX_DESTRUCTOR_P (fn)))
kono
parents:
diff changeset
491 {
kono
parents:
diff changeset
492 if (!check_clones)
kono
parents:
diff changeset
493 return NULL_TREE;
kono
parents:
diff changeset
494
kono
parents:
diff changeset
495 /* Watch for clones where we constant propagated the first
kono
parents:
diff changeset
496 argument (pointer to the instance). */
kono
parents:
diff changeset
497 fn = DECL_ABSTRACT_ORIGIN (fn);
kono
parents:
diff changeset
498 if (!fn
kono
parents:
diff changeset
499 || TREE_CODE (TREE_TYPE (fn)) != METHOD_TYPE
kono
parents:
diff changeset
500 || (!DECL_CXX_CONSTRUCTOR_P (fn) && !DECL_CXX_DESTRUCTOR_P (fn)))
kono
parents:
diff changeset
501 return NULL_TREE;
kono
parents:
diff changeset
502 }
kono
parents:
diff changeset
503
kono
parents:
diff changeset
504 if (flags_from_decl_or_type (fn) & (ECF_PURE | ECF_CONST))
kono
parents:
diff changeset
505 return NULL_TREE;
kono
parents:
diff changeset
506
kono
parents:
diff changeset
507 return fn;
kono
parents:
diff changeset
508 }
kono
parents:
diff changeset
509
kono
parents:
diff changeset
510 /* Return a FUNCTION_DECL if BLOCK represents a constructor or destructor.
kono
parents:
diff changeset
511 If CHECK_CLONES is true, also check for clones of ctor/dtors. */
kono
parents:
diff changeset
512
kono
parents:
diff changeset
513 tree
kono
parents:
diff changeset
514 inlined_polymorphic_ctor_dtor_block_p (tree block, bool check_clones)
kono
parents:
diff changeset
515 {
kono
parents:
diff changeset
516 tree fn = block_ultimate_origin (block);
kono
parents:
diff changeset
517 if (fn == NULL || TREE_CODE (fn) != FUNCTION_DECL)
kono
parents:
diff changeset
518 return NULL_TREE;
kono
parents:
diff changeset
519
kono
parents:
diff changeset
520 return polymorphic_ctor_dtor_p (fn, check_clones);
kono
parents:
diff changeset
521 }
kono
parents:
diff changeset
522
kono
parents:
diff changeset
523
kono
parents:
diff changeset
524 /* We know that the instance is stored in variable or parameter
kono
parents:
diff changeset
525 (not dynamically allocated) and we want to disprove the fact
kono
parents:
diff changeset
526 that it may be in construction at invocation of CALL.
kono
parents:
diff changeset
527
kono
parents:
diff changeset
528 BASE represents memory location where instance is stored.
kono
parents:
diff changeset
529 If BASE is NULL, it is assumed to be global memory.
kono
parents:
diff changeset
530 OUTER_TYPE is known type of the instance or NULL if not
kono
parents:
diff changeset
531 known.
kono
parents:
diff changeset
532
kono
parents:
diff changeset
533 For the variable to be in construction we actually need to
kono
parents:
diff changeset
534 be in constructor of corresponding global variable or
kono
parents:
diff changeset
535 the inline stack of CALL must contain the constructor.
kono
parents:
diff changeset
536 Check this condition. This check works safely only before
kono
parents:
diff changeset
537 IPA passes, because inline stacks may become out of date
kono
parents:
diff changeset
538 later. */
kono
parents:
diff changeset
539
kono
parents:
diff changeset
540 bool
kono
parents:
diff changeset
541 decl_maybe_in_construction_p (tree base, tree outer_type,
kono
parents:
diff changeset
542 gimple *call, tree function)
kono
parents:
diff changeset
543 {
kono
parents:
diff changeset
544 if (outer_type)
kono
parents:
diff changeset
545 outer_type = TYPE_MAIN_VARIANT (outer_type);
kono
parents:
diff changeset
546 gcc_assert (!base || DECL_P (base));
kono
parents:
diff changeset
547
kono
parents:
diff changeset
548 /* After inlining the code unification optimizations may invalidate
kono
parents:
diff changeset
549 inline stacks. Also we need to give up on global variables after
kono
parents:
diff changeset
550 IPA, because addresses of these may have been propagated to their
kono
parents:
diff changeset
551 constructors. */
kono
parents:
diff changeset
552 if (DECL_STRUCT_FUNCTION (function)->after_inlining)
kono
parents:
diff changeset
553 return true;
kono
parents:
diff changeset
554
kono
parents:
diff changeset
555 /* Pure functions can not do any changes on the dynamic type;
kono
parents:
diff changeset
556 that require writting to memory. */
kono
parents:
diff changeset
557 if ((!base || !auto_var_in_fn_p (base, function))
kono
parents:
diff changeset
558 && flags_from_decl_or_type (function) & (ECF_PURE | ECF_CONST))
kono
parents:
diff changeset
559 return false;
kono
parents:
diff changeset
560
kono
parents:
diff changeset
561 bool check_clones = !base || is_global_var (base);
kono
parents:
diff changeset
562 for (tree block = gimple_block (call); block && TREE_CODE (block) == BLOCK;
kono
parents:
diff changeset
563 block = BLOCK_SUPERCONTEXT (block))
kono
parents:
diff changeset
564 if (tree fn = inlined_polymorphic_ctor_dtor_block_p (block, check_clones))
kono
parents:
diff changeset
565 {
kono
parents:
diff changeset
566 tree type = TYPE_METHOD_BASETYPE (TREE_TYPE (fn));
kono
parents:
diff changeset
567
kono
parents:
diff changeset
568 if (!outer_type || !types_odr_comparable (type, outer_type))
kono
parents:
diff changeset
569 {
kono
parents:
diff changeset
570 if (TREE_CODE (type) == RECORD_TYPE
kono
parents:
diff changeset
571 && TYPE_BINFO (type)
kono
parents:
diff changeset
572 && polymorphic_type_binfo_p (TYPE_BINFO (type)))
kono
parents:
diff changeset
573 return true;
kono
parents:
diff changeset
574 }
kono
parents:
diff changeset
575 else if (types_same_for_odr (type, outer_type))
kono
parents:
diff changeset
576 return true;
kono
parents:
diff changeset
577 }
kono
parents:
diff changeset
578
kono
parents:
diff changeset
579 if (!base || (VAR_P (base) && is_global_var (base)))
kono
parents:
diff changeset
580 {
kono
parents:
diff changeset
581 if (TREE_CODE (TREE_TYPE (function)) != METHOD_TYPE
kono
parents:
diff changeset
582 || (!DECL_CXX_CONSTRUCTOR_P (function)
kono
parents:
diff changeset
583 && !DECL_CXX_DESTRUCTOR_P (function)))
kono
parents:
diff changeset
584 {
kono
parents:
diff changeset
585 if (!DECL_ABSTRACT_ORIGIN (function))
kono
parents:
diff changeset
586 return false;
kono
parents:
diff changeset
587 /* Watch for clones where we constant propagated the first
kono
parents:
diff changeset
588 argument (pointer to the instance). */
kono
parents:
diff changeset
589 function = DECL_ABSTRACT_ORIGIN (function);
kono
parents:
diff changeset
590 if (!function
kono
parents:
diff changeset
591 || TREE_CODE (TREE_TYPE (function)) != METHOD_TYPE
kono
parents:
diff changeset
592 || (!DECL_CXX_CONSTRUCTOR_P (function)
kono
parents:
diff changeset
593 && !DECL_CXX_DESTRUCTOR_P (function)))
kono
parents:
diff changeset
594 return false;
kono
parents:
diff changeset
595 }
kono
parents:
diff changeset
596 tree type = TYPE_METHOD_BASETYPE (TREE_TYPE (function));
kono
parents:
diff changeset
597 if (!outer_type || !types_odr_comparable (type, outer_type))
kono
parents:
diff changeset
598 {
kono
parents:
diff changeset
599 if (TREE_CODE (type) == RECORD_TYPE
kono
parents:
diff changeset
600 && TYPE_BINFO (type)
kono
parents:
diff changeset
601 && polymorphic_type_binfo_p (TYPE_BINFO (type)))
kono
parents:
diff changeset
602 return true;
kono
parents:
diff changeset
603 }
kono
parents:
diff changeset
604 else if (types_same_for_odr (type, outer_type))
kono
parents:
diff changeset
605 return true;
kono
parents:
diff changeset
606 }
kono
parents:
diff changeset
607 return false;
kono
parents:
diff changeset
608 }
kono
parents:
diff changeset
609
kono
parents:
diff changeset
610 /* Dump human readable context to F. If NEWLINE is true, it will be terminated
kono
parents:
diff changeset
611 by a newline. */
kono
parents:
diff changeset
612
kono
parents:
diff changeset
613 void
kono
parents:
diff changeset
614 ipa_polymorphic_call_context::dump (FILE *f, bool newline) const
kono
parents:
diff changeset
615 {
kono
parents:
diff changeset
616 fprintf (f, " ");
kono
parents:
diff changeset
617 if (invalid)
kono
parents:
diff changeset
618 fprintf (f, "Call is known to be undefined");
kono
parents:
diff changeset
619 else
kono
parents:
diff changeset
620 {
kono
parents:
diff changeset
621 if (useless_p ())
kono
parents:
diff changeset
622 fprintf (f, "nothing known");
kono
parents:
diff changeset
623 if (outer_type || offset)
kono
parents:
diff changeset
624 {
kono
parents:
diff changeset
625 fprintf (f, "Outer type%s:", dynamic ? " (dynamic)":"");
kono
parents:
diff changeset
626 print_generic_expr (f, outer_type, TDF_SLIM);
kono
parents:
diff changeset
627 if (maybe_derived_type)
kono
parents:
diff changeset
628 fprintf (f, " (or a derived type)");
kono
parents:
diff changeset
629 if (maybe_in_construction)
kono
parents:
diff changeset
630 fprintf (f, " (maybe in construction)");
kono
parents:
diff changeset
631 fprintf (f, " offset " HOST_WIDE_INT_PRINT_DEC,
kono
parents:
diff changeset
632 offset);
kono
parents:
diff changeset
633 }
kono
parents:
diff changeset
634 if (speculative_outer_type)
kono
parents:
diff changeset
635 {
kono
parents:
diff changeset
636 if (outer_type || offset)
kono
parents:
diff changeset
637 fprintf (f, " ");
kono
parents:
diff changeset
638 fprintf (f, "Speculative outer type:");
kono
parents:
diff changeset
639 print_generic_expr (f, speculative_outer_type, TDF_SLIM);
kono
parents:
diff changeset
640 if (speculative_maybe_derived_type)
kono
parents:
diff changeset
641 fprintf (f, " (or a derived type)");
kono
parents:
diff changeset
642 fprintf (f, " at offset " HOST_WIDE_INT_PRINT_DEC,
kono
parents:
diff changeset
643 speculative_offset);
kono
parents:
diff changeset
644 }
kono
parents:
diff changeset
645 }
kono
parents:
diff changeset
646 if (newline)
kono
parents:
diff changeset
647 fprintf(f, "\n");
kono
parents:
diff changeset
648 }
kono
parents:
diff changeset
649
kono
parents:
diff changeset
650 /* Print context to stderr. */
kono
parents:
diff changeset
651
kono
parents:
diff changeset
652 void
kono
parents:
diff changeset
653 ipa_polymorphic_call_context::debug () const
kono
parents:
diff changeset
654 {
kono
parents:
diff changeset
655 dump (stderr);
kono
parents:
diff changeset
656 }
kono
parents:
diff changeset
657
kono
parents:
diff changeset
658 /* Stream out the context to OB. */
kono
parents:
diff changeset
659
kono
parents:
diff changeset
660 void
kono
parents:
diff changeset
661 ipa_polymorphic_call_context::stream_out (struct output_block *ob) const
kono
parents:
diff changeset
662 {
kono
parents:
diff changeset
663 struct bitpack_d bp = bitpack_create (ob->main_stream);
kono
parents:
diff changeset
664
kono
parents:
diff changeset
665 bp_pack_value (&bp, invalid, 1);
kono
parents:
diff changeset
666 bp_pack_value (&bp, maybe_in_construction, 1);
kono
parents:
diff changeset
667 bp_pack_value (&bp, maybe_derived_type, 1);
kono
parents:
diff changeset
668 bp_pack_value (&bp, speculative_maybe_derived_type, 1);
kono
parents:
diff changeset
669 bp_pack_value (&bp, dynamic, 1);
kono
parents:
diff changeset
670 bp_pack_value (&bp, outer_type != NULL, 1);
kono
parents:
diff changeset
671 bp_pack_value (&bp, offset != 0, 1);
kono
parents:
diff changeset
672 bp_pack_value (&bp, speculative_outer_type != NULL, 1);
kono
parents:
diff changeset
673 streamer_write_bitpack (&bp);
kono
parents:
diff changeset
674
kono
parents:
diff changeset
675 if (outer_type != NULL)
kono
parents:
diff changeset
676 stream_write_tree (ob, outer_type, true);
kono
parents:
diff changeset
677 if (offset)
kono
parents:
diff changeset
678 streamer_write_hwi (ob, offset);
kono
parents:
diff changeset
679 if (speculative_outer_type != NULL)
kono
parents:
diff changeset
680 {
kono
parents:
diff changeset
681 stream_write_tree (ob, speculative_outer_type, true);
kono
parents:
diff changeset
682 streamer_write_hwi (ob, speculative_offset);
kono
parents:
diff changeset
683 }
kono
parents:
diff changeset
684 else
kono
parents:
diff changeset
685 gcc_assert (!speculative_offset);
kono
parents:
diff changeset
686 }
kono
parents:
diff changeset
687
kono
parents:
diff changeset
688 /* Stream in the context from IB and DATA_IN. */
kono
parents:
diff changeset
689
kono
parents:
diff changeset
690 void
kono
parents:
diff changeset
691 ipa_polymorphic_call_context::stream_in (struct lto_input_block *ib,
kono
parents:
diff changeset
692 struct data_in *data_in)
kono
parents:
diff changeset
693 {
kono
parents:
diff changeset
694 struct bitpack_d bp = streamer_read_bitpack (ib);
kono
parents:
diff changeset
695
kono
parents:
diff changeset
696 invalid = bp_unpack_value (&bp, 1);
kono
parents:
diff changeset
697 maybe_in_construction = bp_unpack_value (&bp, 1);
kono
parents:
diff changeset
698 maybe_derived_type = bp_unpack_value (&bp, 1);
kono
parents:
diff changeset
699 speculative_maybe_derived_type = bp_unpack_value (&bp, 1);
kono
parents:
diff changeset
700 dynamic = bp_unpack_value (&bp, 1);
kono
parents:
diff changeset
701 bool outer_type_p = bp_unpack_value (&bp, 1);
kono
parents:
diff changeset
702 bool offset_p = bp_unpack_value (&bp, 1);
kono
parents:
diff changeset
703 bool speculative_outer_type_p = bp_unpack_value (&bp, 1);
kono
parents:
diff changeset
704
kono
parents:
diff changeset
705 if (outer_type_p)
kono
parents:
diff changeset
706 outer_type = stream_read_tree (ib, data_in);
kono
parents:
diff changeset
707 else
kono
parents:
diff changeset
708 outer_type = NULL;
kono
parents:
diff changeset
709 if (offset_p)
kono
parents:
diff changeset
710 offset = (HOST_WIDE_INT) streamer_read_hwi (ib);
kono
parents:
diff changeset
711 else
kono
parents:
diff changeset
712 offset = 0;
kono
parents:
diff changeset
713 if (speculative_outer_type_p)
kono
parents:
diff changeset
714 {
kono
parents:
diff changeset
715 speculative_outer_type = stream_read_tree (ib, data_in);
kono
parents:
diff changeset
716 speculative_offset = (HOST_WIDE_INT) streamer_read_hwi (ib);
kono
parents:
diff changeset
717 }
kono
parents:
diff changeset
718 else
kono
parents:
diff changeset
719 {
kono
parents:
diff changeset
720 speculative_outer_type = NULL;
kono
parents:
diff changeset
721 speculative_offset = 0;
kono
parents:
diff changeset
722 }
kono
parents:
diff changeset
723 }
kono
parents:
diff changeset
724
kono
parents:
diff changeset
725 /* Proudce polymorphic call context for call method of instance
kono
parents:
diff changeset
726 that is located within BASE (that is assumed to be a decl) at offset OFF. */
kono
parents:
diff changeset
727
kono
parents:
diff changeset
728 void
kono
parents:
diff changeset
729 ipa_polymorphic_call_context::set_by_decl (tree base, HOST_WIDE_INT off)
kono
parents:
diff changeset
730 {
kono
parents:
diff changeset
731 gcc_assert (DECL_P (base));
kono
parents:
diff changeset
732 clear_speculation ();
kono
parents:
diff changeset
733
kono
parents:
diff changeset
734 if (!contains_polymorphic_type_p (TREE_TYPE (base)))
kono
parents:
diff changeset
735 {
kono
parents:
diff changeset
736 clear_outer_type ();
kono
parents:
diff changeset
737 offset = off;
kono
parents:
diff changeset
738 return;
kono
parents:
diff changeset
739 }
kono
parents:
diff changeset
740 outer_type = TYPE_MAIN_VARIANT (TREE_TYPE (base));
kono
parents:
diff changeset
741 offset = off;
kono
parents:
diff changeset
742 /* Make very conservative assumption that all objects
kono
parents:
diff changeset
743 may be in construction.
kono
parents:
diff changeset
744
kono
parents:
diff changeset
745 It is up to caller to revisit this via
kono
parents:
diff changeset
746 get_dynamic_type or decl_maybe_in_construction_p. */
kono
parents:
diff changeset
747 maybe_in_construction = true;
kono
parents:
diff changeset
748 maybe_derived_type = false;
kono
parents:
diff changeset
749 dynamic = false;
kono
parents:
diff changeset
750 }
kono
parents:
diff changeset
751
kono
parents:
diff changeset
752 /* CST is an invariant (address of decl), try to get meaningful
kono
parents:
diff changeset
753 polymorphic call context for polymorphic call of method
kono
parents:
diff changeset
754 if instance of OTR_TYPE that is located at offset OFF of this invariant.
kono
parents:
diff changeset
755 Return FALSE if nothing meaningful can be found. */
kono
parents:
diff changeset
756
kono
parents:
diff changeset
757 bool
kono
parents:
diff changeset
758 ipa_polymorphic_call_context::set_by_invariant (tree cst,
kono
parents:
diff changeset
759 tree otr_type,
kono
parents:
diff changeset
760 HOST_WIDE_INT off)
kono
parents:
diff changeset
761 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
762 poly_int64 offset2, size, max_size;
111
kono
parents:
diff changeset
763 bool reverse;
kono
parents:
diff changeset
764 tree base;
kono
parents:
diff changeset
765
kono
parents:
diff changeset
766 invalid = false;
kono
parents:
diff changeset
767 off = 0;
kono
parents:
diff changeset
768 clear_outer_type (otr_type);
kono
parents:
diff changeset
769
kono
parents:
diff changeset
770 if (TREE_CODE (cst) != ADDR_EXPR)
kono
parents:
diff changeset
771 return false;
kono
parents:
diff changeset
772
kono
parents:
diff changeset
773 cst = TREE_OPERAND (cst, 0);
kono
parents:
diff changeset
774 base = get_ref_base_and_extent (cst, &offset2, &size, &max_size, &reverse);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
775 if (!DECL_P (base) || !known_size_p (max_size) || maybe_ne (max_size, size))
111
kono
parents:
diff changeset
776 return false;
kono
parents:
diff changeset
777
kono
parents:
diff changeset
778 /* Only type inconsistent programs can have otr_type that is
kono
parents:
diff changeset
779 not part of outer type. */
kono
parents:
diff changeset
780 if (otr_type && !contains_type_p (TREE_TYPE (base), off, otr_type))
kono
parents:
diff changeset
781 return false;
kono
parents:
diff changeset
782
kono
parents:
diff changeset
783 set_by_decl (base, off);
kono
parents:
diff changeset
784 return true;
kono
parents:
diff changeset
785 }
kono
parents:
diff changeset
786
kono
parents:
diff changeset
787 /* See if OP is SSA name initialized as a copy or by single assignment.
kono
parents:
diff changeset
788 If so, walk the SSA graph up. Because simple PHI conditional is considered
kono
parents:
diff changeset
789 copy, GLOBAL_VISITED may be used to avoid infinite loop walking the SSA
kono
parents:
diff changeset
790 graph. */
kono
parents:
diff changeset
791
kono
parents:
diff changeset
792 static tree
kono
parents:
diff changeset
793 walk_ssa_copies (tree op, hash_set<tree> **global_visited = NULL)
kono
parents:
diff changeset
794 {
kono
parents:
diff changeset
795 hash_set <tree> *visited = NULL;
kono
parents:
diff changeset
796 STRIP_NOPS (op);
kono
parents:
diff changeset
797 while (TREE_CODE (op) == SSA_NAME
kono
parents:
diff changeset
798 && !SSA_NAME_IS_DEFAULT_DEF (op)
kono
parents:
diff changeset
799 /* We might be called via fold_stmt during cfgcleanup where
kono
parents:
diff changeset
800 SSA form need not be up-to-date. */
kono
parents:
diff changeset
801 && !name_registered_for_update_p (op)
kono
parents:
diff changeset
802 && (gimple_assign_single_p (SSA_NAME_DEF_STMT (op))
kono
parents:
diff changeset
803 || gimple_code (SSA_NAME_DEF_STMT (op)) == GIMPLE_PHI))
kono
parents:
diff changeset
804 {
kono
parents:
diff changeset
805 if (global_visited)
kono
parents:
diff changeset
806 {
kono
parents:
diff changeset
807 if (!*global_visited)
kono
parents:
diff changeset
808 *global_visited = new hash_set<tree>;
kono
parents:
diff changeset
809 if ((*global_visited)->add (op))
kono
parents:
diff changeset
810 goto done;
kono
parents:
diff changeset
811 }
kono
parents:
diff changeset
812 else
kono
parents:
diff changeset
813 {
kono
parents:
diff changeset
814 if (!visited)
kono
parents:
diff changeset
815 visited = new hash_set<tree>;
kono
parents:
diff changeset
816 if (visited->add (op))
kono
parents:
diff changeset
817 goto done;
kono
parents:
diff changeset
818 }
kono
parents:
diff changeset
819 /* Special case
kono
parents:
diff changeset
820 if (ptr == 0)
kono
parents:
diff changeset
821 ptr = 0;
kono
parents:
diff changeset
822 else
kono
parents:
diff changeset
823 ptr = ptr.foo;
kono
parents:
diff changeset
824 This pattern is implicitly produced for casts to non-primary
kono
parents:
diff changeset
825 bases. When doing context analysis, we do not really care
kono
parents:
diff changeset
826 about the case pointer is NULL, because the call will be
kono
parents:
diff changeset
827 undefined anyway. */
kono
parents:
diff changeset
828 if (gimple_code (SSA_NAME_DEF_STMT (op)) == GIMPLE_PHI)
kono
parents:
diff changeset
829 {
kono
parents:
diff changeset
830 gimple *phi = SSA_NAME_DEF_STMT (op);
kono
parents:
diff changeset
831
kono
parents:
diff changeset
832 if (gimple_phi_num_args (phi) > 2)
kono
parents:
diff changeset
833 goto done;
kono
parents:
diff changeset
834 if (gimple_phi_num_args (phi) == 1)
kono
parents:
diff changeset
835 op = gimple_phi_arg_def (phi, 0);
kono
parents:
diff changeset
836 else if (integer_zerop (gimple_phi_arg_def (phi, 0)))
kono
parents:
diff changeset
837 op = gimple_phi_arg_def (phi, 1);
kono
parents:
diff changeset
838 else if (integer_zerop (gimple_phi_arg_def (phi, 1)))
kono
parents:
diff changeset
839 op = gimple_phi_arg_def (phi, 0);
kono
parents:
diff changeset
840 else
kono
parents:
diff changeset
841 goto done;
kono
parents:
diff changeset
842 }
kono
parents:
diff changeset
843 else
kono
parents:
diff changeset
844 {
kono
parents:
diff changeset
845 if (gimple_assign_load_p (SSA_NAME_DEF_STMT (op)))
kono
parents:
diff changeset
846 goto done;
kono
parents:
diff changeset
847 op = gimple_assign_rhs1 (SSA_NAME_DEF_STMT (op));
kono
parents:
diff changeset
848 }
kono
parents:
diff changeset
849 STRIP_NOPS (op);
kono
parents:
diff changeset
850 }
kono
parents:
diff changeset
851 done:
kono
parents:
diff changeset
852 if (visited)
kono
parents:
diff changeset
853 delete (visited);
kono
parents:
diff changeset
854 return op;
kono
parents:
diff changeset
855 }
kono
parents:
diff changeset
856
kono
parents:
diff changeset
857 /* Create polymorphic call context from IP invariant CST.
kono
parents:
diff changeset
858 This is typically &global_var.
kono
parents:
diff changeset
859 OTR_TYPE specify type of polymorphic call or NULL if unknown, OFF
kono
parents:
diff changeset
860 is offset of call. */
kono
parents:
diff changeset
861
kono
parents:
diff changeset
862 ipa_polymorphic_call_context::ipa_polymorphic_call_context (tree cst,
kono
parents:
diff changeset
863 tree otr_type,
kono
parents:
diff changeset
864 HOST_WIDE_INT off)
kono
parents:
diff changeset
865 {
kono
parents:
diff changeset
866 clear_speculation ();
kono
parents:
diff changeset
867 set_by_invariant (cst, otr_type, off);
kono
parents:
diff changeset
868 }
kono
parents:
diff changeset
869
kono
parents:
diff changeset
870 /* Build context for pointer REF contained in FNDECL at statement STMT.
kono
parents:
diff changeset
871 if INSTANCE is non-NULL, return pointer to the object described by
kono
parents:
diff changeset
872 the context or DECL where context is contained in. */
kono
parents:
diff changeset
873
kono
parents:
diff changeset
874 ipa_polymorphic_call_context::ipa_polymorphic_call_context (tree fndecl,
kono
parents:
diff changeset
875 tree ref,
kono
parents:
diff changeset
876 gimple *stmt,
kono
parents:
diff changeset
877 tree *instance)
kono
parents:
diff changeset
878 {
kono
parents:
diff changeset
879 tree otr_type = NULL;
kono
parents:
diff changeset
880 tree base_pointer;
kono
parents:
diff changeset
881 hash_set <tree> *visited = NULL;
kono
parents:
diff changeset
882
kono
parents:
diff changeset
883 if (TREE_CODE (ref) == OBJ_TYPE_REF)
kono
parents:
diff changeset
884 {
kono
parents:
diff changeset
885 otr_type = obj_type_ref_class (ref);
kono
parents:
diff changeset
886 base_pointer = OBJ_TYPE_REF_OBJECT (ref);
kono
parents:
diff changeset
887 }
kono
parents:
diff changeset
888 else
kono
parents:
diff changeset
889 base_pointer = ref;
kono
parents:
diff changeset
890
kono
parents:
diff changeset
891 /* Set up basic info in case we find nothing interesting in the analysis. */
kono
parents:
diff changeset
892 clear_speculation ();
kono
parents:
diff changeset
893 clear_outer_type (otr_type);
kono
parents:
diff changeset
894 invalid = false;
kono
parents:
diff changeset
895
kono
parents:
diff changeset
896 /* Walk SSA for outer object. */
kono
parents:
diff changeset
897 while (true)
kono
parents:
diff changeset
898 {
kono
parents:
diff changeset
899 base_pointer = walk_ssa_copies (base_pointer, &visited);
kono
parents:
diff changeset
900 if (TREE_CODE (base_pointer) == ADDR_EXPR)
kono
parents:
diff changeset
901 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
902 HOST_WIDE_INT offset2, size;
111
kono
parents:
diff changeset
903 bool reverse;
kono
parents:
diff changeset
904 tree base
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
905 = get_ref_base_and_extent_hwi (TREE_OPERAND (base_pointer, 0),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
906 &offset2, &size, &reverse);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
907 if (!base)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
908 break;
111
kono
parents:
diff changeset
909
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
910 combine_speculation_with (TYPE_MAIN_VARIANT (TREE_TYPE (base)),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
911 offset + offset2,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
912 true,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
913 NULL /* Do not change outer type. */);
111
kono
parents:
diff changeset
914
kono
parents:
diff changeset
915 /* If this is a varying address, punt. */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
916 if (TREE_CODE (base) == MEM_REF || DECL_P (base))
111
kono
parents:
diff changeset
917 {
kono
parents:
diff changeset
918 /* We found dereference of a pointer. Type of the pointer
kono
parents:
diff changeset
919 and MEM_REF is meaningless, but we can look futher. */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
920 offset_int mem_offset;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
921 if (TREE_CODE (base) == MEM_REF
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
922 && mem_ref_offset (base).is_constant (&mem_offset))
111
kono
parents:
diff changeset
923 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
924 offset_int o = mem_offset * BITS_PER_UNIT;
111
kono
parents:
diff changeset
925 o += offset;
kono
parents:
diff changeset
926 o += offset2;
kono
parents:
diff changeset
927 if (!wi::fits_shwi_p (o))
kono
parents:
diff changeset
928 break;
kono
parents:
diff changeset
929 base_pointer = TREE_OPERAND (base, 0);
kono
parents:
diff changeset
930 offset = o.to_shwi ();
kono
parents:
diff changeset
931 outer_type = NULL;
kono
parents:
diff changeset
932 }
kono
parents:
diff changeset
933 /* We found base object. In this case the outer_type
kono
parents:
diff changeset
934 is known. */
kono
parents:
diff changeset
935 else if (DECL_P (base))
kono
parents:
diff changeset
936 {
kono
parents:
diff changeset
937 if (visited)
kono
parents:
diff changeset
938 delete (visited);
kono
parents:
diff changeset
939 /* Only type inconsistent programs can have otr_type that is
kono
parents:
diff changeset
940 not part of outer type. */
kono
parents:
diff changeset
941 if (otr_type
kono
parents:
diff changeset
942 && !contains_type_p (TREE_TYPE (base),
kono
parents:
diff changeset
943 offset + offset2, otr_type))
kono
parents:
diff changeset
944 {
kono
parents:
diff changeset
945 invalid = true;
kono
parents:
diff changeset
946 if (instance)
kono
parents:
diff changeset
947 *instance = base_pointer;
kono
parents:
diff changeset
948 return;
kono
parents:
diff changeset
949 }
kono
parents:
diff changeset
950 set_by_decl (base, offset + offset2);
kono
parents:
diff changeset
951 if (outer_type && maybe_in_construction && stmt)
kono
parents:
diff changeset
952 maybe_in_construction
kono
parents:
diff changeset
953 = decl_maybe_in_construction_p (base,
kono
parents:
diff changeset
954 outer_type,
kono
parents:
diff changeset
955 stmt,
kono
parents:
diff changeset
956 fndecl);
kono
parents:
diff changeset
957 if (instance)
kono
parents:
diff changeset
958 *instance = base;
kono
parents:
diff changeset
959 return;
kono
parents:
diff changeset
960 }
kono
parents:
diff changeset
961 else
kono
parents:
diff changeset
962 break;
kono
parents:
diff changeset
963 }
kono
parents:
diff changeset
964 else
kono
parents:
diff changeset
965 break;
kono
parents:
diff changeset
966 }
kono
parents:
diff changeset
967 else if (TREE_CODE (base_pointer) == POINTER_PLUS_EXPR
kono
parents:
diff changeset
968 && TREE_CODE (TREE_OPERAND (base_pointer, 1)) == INTEGER_CST)
kono
parents:
diff changeset
969 {
kono
parents:
diff changeset
970 offset_int o
kono
parents:
diff changeset
971 = offset_int::from (wi::to_wide (TREE_OPERAND (base_pointer, 1)),
kono
parents:
diff changeset
972 SIGNED);
kono
parents:
diff changeset
973 o *= BITS_PER_UNIT;
kono
parents:
diff changeset
974 o += offset;
kono
parents:
diff changeset
975 if (!wi::fits_shwi_p (o))
kono
parents:
diff changeset
976 break;
kono
parents:
diff changeset
977 offset = o.to_shwi ();
kono
parents:
diff changeset
978 base_pointer = TREE_OPERAND (base_pointer, 0);
kono
parents:
diff changeset
979 }
kono
parents:
diff changeset
980 else
kono
parents:
diff changeset
981 break;
kono
parents:
diff changeset
982 }
kono
parents:
diff changeset
983
kono
parents:
diff changeset
984 if (visited)
kono
parents:
diff changeset
985 delete (visited);
kono
parents:
diff changeset
986
kono
parents:
diff changeset
987 /* Try to determine type of the outer object. */
kono
parents:
diff changeset
988 if (TREE_CODE (base_pointer) == SSA_NAME
kono
parents:
diff changeset
989 && SSA_NAME_IS_DEFAULT_DEF (base_pointer)
kono
parents:
diff changeset
990 && TREE_CODE (SSA_NAME_VAR (base_pointer)) == PARM_DECL)
kono
parents:
diff changeset
991 {
kono
parents:
diff changeset
992 /* See if parameter is THIS pointer of a method. */
kono
parents:
diff changeset
993 if (TREE_CODE (TREE_TYPE (fndecl)) == METHOD_TYPE
kono
parents:
diff changeset
994 && SSA_NAME_VAR (base_pointer) == DECL_ARGUMENTS (fndecl))
kono
parents:
diff changeset
995 {
kono
parents:
diff changeset
996 outer_type
kono
parents:
diff changeset
997 = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (base_pointer)));
kono
parents:
diff changeset
998 gcc_assert (TREE_CODE (outer_type) == RECORD_TYPE
kono
parents:
diff changeset
999 || TREE_CODE (outer_type) == UNION_TYPE);
kono
parents:
diff changeset
1000
kono
parents:
diff changeset
1001 /* Dynamic casting has possibly upcasted the type
kono
parents:
diff changeset
1002 in the hiearchy. In this case outer type is less
kono
parents:
diff changeset
1003 informative than inner type and we should forget
kono
parents:
diff changeset
1004 about it. */
kono
parents:
diff changeset
1005 if ((otr_type
kono
parents:
diff changeset
1006 && !contains_type_p (outer_type, offset,
kono
parents:
diff changeset
1007 otr_type))
kono
parents:
diff changeset
1008 || !contains_polymorphic_type_p (outer_type))
kono
parents:
diff changeset
1009 {
kono
parents:
diff changeset
1010 outer_type = NULL;
kono
parents:
diff changeset
1011 if (instance)
kono
parents:
diff changeset
1012 *instance = base_pointer;
kono
parents:
diff changeset
1013 return;
kono
parents:
diff changeset
1014 }
kono
parents:
diff changeset
1015
kono
parents:
diff changeset
1016 dynamic = true;
kono
parents:
diff changeset
1017
kono
parents:
diff changeset
1018 /* If the function is constructor or destructor, then
kono
parents:
diff changeset
1019 the type is possibly in construction, but we know
kono
parents:
diff changeset
1020 it is not derived type. */
kono
parents:
diff changeset
1021 if (DECL_CXX_CONSTRUCTOR_P (fndecl)
kono
parents:
diff changeset
1022 || DECL_CXX_DESTRUCTOR_P (fndecl))
kono
parents:
diff changeset
1023 {
kono
parents:
diff changeset
1024 maybe_in_construction = true;
kono
parents:
diff changeset
1025 maybe_derived_type = false;
kono
parents:
diff changeset
1026 }
kono
parents:
diff changeset
1027 else
kono
parents:
diff changeset
1028 {
kono
parents:
diff changeset
1029 maybe_derived_type = true;
kono
parents:
diff changeset
1030 maybe_in_construction = false;
kono
parents:
diff changeset
1031 }
kono
parents:
diff changeset
1032 if (instance)
kono
parents:
diff changeset
1033 *instance = base_pointer;
kono
parents:
diff changeset
1034 return;
kono
parents:
diff changeset
1035 }
kono
parents:
diff changeset
1036 /* Non-PODs passed by value are really passed by invisible
kono
parents:
diff changeset
1037 reference. In this case we also know the type of the
kono
parents:
diff changeset
1038 object. */
kono
parents:
diff changeset
1039 if (DECL_BY_REFERENCE (SSA_NAME_VAR (base_pointer)))
kono
parents:
diff changeset
1040 {
kono
parents:
diff changeset
1041 outer_type
kono
parents:
diff changeset
1042 = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (base_pointer)));
kono
parents:
diff changeset
1043 /* Only type inconsistent programs can have otr_type that is
kono
parents:
diff changeset
1044 not part of outer type. */
kono
parents:
diff changeset
1045 if (otr_type && !contains_type_p (outer_type, offset,
kono
parents:
diff changeset
1046 otr_type))
kono
parents:
diff changeset
1047 {
kono
parents:
diff changeset
1048 invalid = true;
kono
parents:
diff changeset
1049 if (instance)
kono
parents:
diff changeset
1050 *instance = base_pointer;
kono
parents:
diff changeset
1051 return;
kono
parents:
diff changeset
1052 }
kono
parents:
diff changeset
1053 /* Non-polymorphic types have no interest for us. */
kono
parents:
diff changeset
1054 else if (!otr_type && !contains_polymorphic_type_p (outer_type))
kono
parents:
diff changeset
1055 {
kono
parents:
diff changeset
1056 outer_type = NULL;
kono
parents:
diff changeset
1057 if (instance)
kono
parents:
diff changeset
1058 *instance = base_pointer;
kono
parents:
diff changeset
1059 return;
kono
parents:
diff changeset
1060 }
kono
parents:
diff changeset
1061 maybe_derived_type = false;
kono
parents:
diff changeset
1062 maybe_in_construction = false;
kono
parents:
diff changeset
1063 if (instance)
kono
parents:
diff changeset
1064 *instance = base_pointer;
kono
parents:
diff changeset
1065 return;
kono
parents:
diff changeset
1066 }
kono
parents:
diff changeset
1067 }
kono
parents:
diff changeset
1068
kono
parents:
diff changeset
1069 tree base_type = TREE_TYPE (base_pointer);
kono
parents:
diff changeset
1070
kono
parents:
diff changeset
1071 if (TREE_CODE (base_pointer) == SSA_NAME
kono
parents:
diff changeset
1072 && SSA_NAME_IS_DEFAULT_DEF (base_pointer)
kono
parents:
diff changeset
1073 && !(TREE_CODE (SSA_NAME_VAR (base_pointer)) == PARM_DECL
kono
parents:
diff changeset
1074 || TREE_CODE (SSA_NAME_VAR (base_pointer)) == RESULT_DECL))
kono
parents:
diff changeset
1075 {
kono
parents:
diff changeset
1076 invalid = true;
kono
parents:
diff changeset
1077 if (instance)
kono
parents:
diff changeset
1078 *instance = base_pointer;
kono
parents:
diff changeset
1079 return;
kono
parents:
diff changeset
1080 }
kono
parents:
diff changeset
1081 if (TREE_CODE (base_pointer) == SSA_NAME
kono
parents:
diff changeset
1082 && SSA_NAME_DEF_STMT (base_pointer)
kono
parents:
diff changeset
1083 && gimple_assign_single_p (SSA_NAME_DEF_STMT (base_pointer)))
kono
parents:
diff changeset
1084 base_type = TREE_TYPE (gimple_assign_rhs1
kono
parents:
diff changeset
1085 (SSA_NAME_DEF_STMT (base_pointer)));
kono
parents:
diff changeset
1086
kono
parents:
diff changeset
1087 if (base_type && POINTER_TYPE_P (base_type))
kono
parents:
diff changeset
1088 combine_speculation_with (TYPE_MAIN_VARIANT (TREE_TYPE (base_type)),
kono
parents:
diff changeset
1089 offset,
kono
parents:
diff changeset
1090 true, NULL /* Do not change type here */);
kono
parents:
diff changeset
1091 /* TODO: There are multiple ways to derive a type. For instance
kono
parents:
diff changeset
1092 if BASE_POINTER is passed to an constructor call prior our refernece.
kono
parents:
diff changeset
1093 We do not make this type of flow sensitive analysis yet. */
kono
parents:
diff changeset
1094 if (instance)
kono
parents:
diff changeset
1095 *instance = base_pointer;
kono
parents:
diff changeset
1096 return;
kono
parents:
diff changeset
1097 }
kono
parents:
diff changeset
1098
kono
parents:
diff changeset
1099 /* Structure to be passed in between detect_type_change and
kono
parents:
diff changeset
1100 check_stmt_for_type_change. */
kono
parents:
diff changeset
1101
kono
parents:
diff changeset
1102 struct type_change_info
kono
parents:
diff changeset
1103 {
kono
parents:
diff changeset
1104 /* Offset into the object where there is the virtual method pointer we are
kono
parents:
diff changeset
1105 looking for. */
kono
parents:
diff changeset
1106 HOST_WIDE_INT offset;
kono
parents:
diff changeset
1107 /* The declaration or SSA_NAME pointer of the base that we are checking for
kono
parents:
diff changeset
1108 type change. */
kono
parents:
diff changeset
1109 tree instance;
kono
parents:
diff changeset
1110 /* The reference to virtual table pointer used. */
kono
parents:
diff changeset
1111 tree vtbl_ptr_ref;
kono
parents:
diff changeset
1112 tree otr_type;
kono
parents:
diff changeset
1113 /* If we actually can tell the type that the object has changed to, it is
kono
parents:
diff changeset
1114 stored in this field. Otherwise it remains NULL_TREE. */
kono
parents:
diff changeset
1115 tree known_current_type;
kono
parents:
diff changeset
1116 HOST_WIDE_INT known_current_offset;
kono
parents:
diff changeset
1117
kono
parents:
diff changeset
1118 /* Set to nonzero if we possibly missed some dynamic type changes and we
kono
parents:
diff changeset
1119 should consider the set to be speculative. */
kono
parents:
diff changeset
1120 unsigned speculative;
kono
parents:
diff changeset
1121
kono
parents:
diff changeset
1122 /* Set to true if dynamic type change has been detected. */
kono
parents:
diff changeset
1123 bool type_maybe_changed;
kono
parents:
diff changeset
1124 /* Set to true if multiple types have been encountered. known_current_type
kono
parents:
diff changeset
1125 must be disregarded in that case. */
kono
parents:
diff changeset
1126 bool multiple_types_encountered;
kono
parents:
diff changeset
1127 bool seen_unanalyzed_store;
kono
parents:
diff changeset
1128 };
kono
parents:
diff changeset
1129
kono
parents:
diff changeset
1130 /* Return true if STMT is not call and can modify a virtual method table pointer.
kono
parents:
diff changeset
1131 We take advantage of fact that vtable stores must appear within constructor
kono
parents:
diff changeset
1132 and destructor functions. */
kono
parents:
diff changeset
1133
kono
parents:
diff changeset
1134 static bool
kono
parents:
diff changeset
1135 noncall_stmt_may_be_vtbl_ptr_store (gimple *stmt)
kono
parents:
diff changeset
1136 {
kono
parents:
diff changeset
1137 if (is_gimple_assign (stmt))
kono
parents:
diff changeset
1138 {
kono
parents:
diff changeset
1139 tree lhs = gimple_assign_lhs (stmt);
kono
parents:
diff changeset
1140
kono
parents:
diff changeset
1141 if (gimple_clobber_p (stmt))
kono
parents:
diff changeset
1142 return false;
kono
parents:
diff changeset
1143 if (!AGGREGATE_TYPE_P (TREE_TYPE (lhs)))
kono
parents:
diff changeset
1144 {
kono
parents:
diff changeset
1145 if (flag_strict_aliasing
kono
parents:
diff changeset
1146 && !POINTER_TYPE_P (TREE_TYPE (lhs)))
kono
parents:
diff changeset
1147 return false;
kono
parents:
diff changeset
1148
kono
parents:
diff changeset
1149 if (TREE_CODE (lhs) == COMPONENT_REF
kono
parents:
diff changeset
1150 && !DECL_VIRTUAL_P (TREE_OPERAND (lhs, 1)))
kono
parents:
diff changeset
1151 return false;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1152 /* In the future we might want to use get_ref_base_and_extent to find
111
kono
parents:
diff changeset
1153 if there is a field corresponding to the offset and if so, proceed
kono
parents:
diff changeset
1154 almost like if it was a component ref. */
kono
parents:
diff changeset
1155 }
kono
parents:
diff changeset
1156 }
kono
parents:
diff changeset
1157
kono
parents:
diff changeset
1158 /* Code unification may mess with inline stacks. */
kono
parents:
diff changeset
1159 if (cfun->after_inlining)
kono
parents:
diff changeset
1160 return true;
kono
parents:
diff changeset
1161
kono
parents:
diff changeset
1162 /* Walk the inline stack and watch out for ctors/dtors.
kono
parents:
diff changeset
1163 TODO: Maybe we can require the store to appear in toplevel
kono
parents:
diff changeset
1164 block of CTOR/DTOR. */
kono
parents:
diff changeset
1165 for (tree block = gimple_block (stmt); block && TREE_CODE (block) == BLOCK;
kono
parents:
diff changeset
1166 block = BLOCK_SUPERCONTEXT (block))
kono
parents:
diff changeset
1167 if (BLOCK_ABSTRACT_ORIGIN (block)
kono
parents:
diff changeset
1168 && TREE_CODE (block_ultimate_origin (block)) == FUNCTION_DECL)
kono
parents:
diff changeset
1169 return inlined_polymorphic_ctor_dtor_block_p (block, false);
kono
parents:
diff changeset
1170 return (TREE_CODE (TREE_TYPE (current_function_decl)) == METHOD_TYPE
kono
parents:
diff changeset
1171 && (DECL_CXX_CONSTRUCTOR_P (current_function_decl)
kono
parents:
diff changeset
1172 || DECL_CXX_DESTRUCTOR_P (current_function_decl)));
kono
parents:
diff changeset
1173 }
kono
parents:
diff changeset
1174
kono
parents:
diff changeset
1175 /* If STMT can be proved to be an assignment to the virtual method table
kono
parents:
diff changeset
1176 pointer of ANALYZED_OBJ and the type associated with the new table
kono
parents:
diff changeset
1177 identified, return the type. Otherwise return NULL_TREE if type changes
kono
parents:
diff changeset
1178 in unknown way or ERROR_MARK_NODE if type is unchanged. */
kono
parents:
diff changeset
1179
kono
parents:
diff changeset
1180 static tree
kono
parents:
diff changeset
1181 extr_type_from_vtbl_ptr_store (gimple *stmt, struct type_change_info *tci,
kono
parents:
diff changeset
1182 HOST_WIDE_INT *type_offset)
kono
parents:
diff changeset
1183 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1184 poly_int64 offset, size, max_size;
111
kono
parents:
diff changeset
1185 tree lhs, rhs, base;
kono
parents:
diff changeset
1186 bool reverse;
kono
parents:
diff changeset
1187
kono
parents:
diff changeset
1188 if (!gimple_assign_single_p (stmt))
kono
parents:
diff changeset
1189 return NULL_TREE;
kono
parents:
diff changeset
1190
kono
parents:
diff changeset
1191 lhs = gimple_assign_lhs (stmt);
kono
parents:
diff changeset
1192 rhs = gimple_assign_rhs1 (stmt);
kono
parents:
diff changeset
1193 if (TREE_CODE (lhs) != COMPONENT_REF
kono
parents:
diff changeset
1194 || !DECL_VIRTUAL_P (TREE_OPERAND (lhs, 1)))
kono
parents:
diff changeset
1195 {
kono
parents:
diff changeset
1196 if (dump_file)
kono
parents:
diff changeset
1197 fprintf (dump_file, " LHS is not virtual table.\n");
kono
parents:
diff changeset
1198 return NULL_TREE;
kono
parents:
diff changeset
1199 }
kono
parents:
diff changeset
1200
kono
parents:
diff changeset
1201 if (tci->vtbl_ptr_ref && operand_equal_p (lhs, tci->vtbl_ptr_ref, 0))
kono
parents:
diff changeset
1202 ;
kono
parents:
diff changeset
1203 else
kono
parents:
diff changeset
1204 {
kono
parents:
diff changeset
1205 base = get_ref_base_and_extent (lhs, &offset, &size, &max_size, &reverse);
kono
parents:
diff changeset
1206 if (DECL_P (tci->instance))
kono
parents:
diff changeset
1207 {
kono
parents:
diff changeset
1208 if (base != tci->instance)
kono
parents:
diff changeset
1209 {
kono
parents:
diff changeset
1210 if (dump_file)
kono
parents:
diff changeset
1211 {
kono
parents:
diff changeset
1212 fprintf (dump_file, " base:");
kono
parents:
diff changeset
1213 print_generic_expr (dump_file, base, TDF_SLIM);
kono
parents:
diff changeset
1214 fprintf (dump_file, " does not match instance:");
kono
parents:
diff changeset
1215 print_generic_expr (dump_file, tci->instance, TDF_SLIM);
kono
parents:
diff changeset
1216 fprintf (dump_file, "\n");
kono
parents:
diff changeset
1217 }
kono
parents:
diff changeset
1218 return NULL_TREE;
kono
parents:
diff changeset
1219 }
kono
parents:
diff changeset
1220 }
kono
parents:
diff changeset
1221 else if (TREE_CODE (base) == MEM_REF)
kono
parents:
diff changeset
1222 {
kono
parents:
diff changeset
1223 if (!operand_equal_p (tci->instance, TREE_OPERAND (base, 0), 0))
kono
parents:
diff changeset
1224 {
kono
parents:
diff changeset
1225 if (dump_file)
kono
parents:
diff changeset
1226 {
kono
parents:
diff changeset
1227 fprintf (dump_file, " base mem ref:");
kono
parents:
diff changeset
1228 print_generic_expr (dump_file, base, TDF_SLIM);
kono
parents:
diff changeset
1229 fprintf (dump_file, " does not match instance:");
kono
parents:
diff changeset
1230 print_generic_expr (dump_file, tci->instance, TDF_SLIM);
kono
parents:
diff changeset
1231 fprintf (dump_file, "\n");
kono
parents:
diff changeset
1232 }
kono
parents:
diff changeset
1233 return NULL_TREE;
kono
parents:
diff changeset
1234 }
kono
parents:
diff changeset
1235 if (!integer_zerop (TREE_OPERAND (base, 1)))
kono
parents:
diff changeset
1236 {
kono
parents:
diff changeset
1237 if (!tree_fits_shwi_p (TREE_OPERAND (base, 1)))
kono
parents:
diff changeset
1238 {
kono
parents:
diff changeset
1239 if (dump_file)
kono
parents:
diff changeset
1240 {
kono
parents:
diff changeset
1241 fprintf (dump_file, " base mem ref:");
kono
parents:
diff changeset
1242 print_generic_expr (dump_file, base, TDF_SLIM);
kono
parents:
diff changeset
1243 fprintf (dump_file, " has non-representable offset:");
kono
parents:
diff changeset
1244 print_generic_expr (dump_file, tci->instance, TDF_SLIM);
kono
parents:
diff changeset
1245 fprintf (dump_file, "\n");
kono
parents:
diff changeset
1246 }
kono
parents:
diff changeset
1247 return NULL_TREE;
kono
parents:
diff changeset
1248 }
kono
parents:
diff changeset
1249 else
kono
parents:
diff changeset
1250 offset += tree_to_shwi (TREE_OPERAND (base, 1)) * BITS_PER_UNIT;
kono
parents:
diff changeset
1251 }
kono
parents:
diff changeset
1252 }
kono
parents:
diff changeset
1253 else if (!operand_equal_p (tci->instance, base, 0)
kono
parents:
diff changeset
1254 || tci->offset)
kono
parents:
diff changeset
1255 {
kono
parents:
diff changeset
1256 if (dump_file)
kono
parents:
diff changeset
1257 {
kono
parents:
diff changeset
1258 fprintf (dump_file, " base:");
kono
parents:
diff changeset
1259 print_generic_expr (dump_file, base, TDF_SLIM);
kono
parents:
diff changeset
1260 fprintf (dump_file, " does not match instance:");
kono
parents:
diff changeset
1261 print_generic_expr (dump_file, tci->instance, TDF_SLIM);
kono
parents:
diff changeset
1262 fprintf (dump_file, " with offset %i\n", (int)tci->offset);
kono
parents:
diff changeset
1263 }
kono
parents:
diff changeset
1264 return tci->offset > POINTER_SIZE ? error_mark_node : NULL_TREE;
kono
parents:
diff changeset
1265 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1266 if (maybe_ne (offset, tci->offset)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1267 || maybe_ne (size, POINTER_SIZE)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1268 || maybe_ne (max_size, POINTER_SIZE))
111
kono
parents:
diff changeset
1269 {
kono
parents:
diff changeset
1270 if (dump_file)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1271 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1272 fprintf (dump_file, " wrong offset ");
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1273 print_dec (offset, dump_file);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1274 fprintf (dump_file, "!=%i or size ", (int) tci->offset);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1275 print_dec (size, dump_file);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1276 fprintf (dump_file, "\n");
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1277 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1278 return (known_le (offset + POINTER_SIZE, tci->offset)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1279 || (known_size_p (max_size)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1280 && known_gt (tci->offset + POINTER_SIZE,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1281 offset + max_size))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1282 ? error_mark_node : NULL);
111
kono
parents:
diff changeset
1283 }
kono
parents:
diff changeset
1284 }
kono
parents:
diff changeset
1285
kono
parents:
diff changeset
1286 tree vtable;
kono
parents:
diff changeset
1287 unsigned HOST_WIDE_INT offset2;
kono
parents:
diff changeset
1288
kono
parents:
diff changeset
1289 if (!vtable_pointer_value_to_vtable (rhs, &vtable, &offset2))
kono
parents:
diff changeset
1290 {
kono
parents:
diff changeset
1291 if (dump_file)
kono
parents:
diff changeset
1292 fprintf (dump_file, " Failed to lookup binfo\n");
kono
parents:
diff changeset
1293 return NULL;
kono
parents:
diff changeset
1294 }
kono
parents:
diff changeset
1295
kono
parents:
diff changeset
1296 tree binfo = subbinfo_with_vtable_at_offset (TYPE_BINFO (DECL_CONTEXT (vtable)),
kono
parents:
diff changeset
1297 offset2, vtable);
kono
parents:
diff changeset
1298 if (!binfo)
kono
parents:
diff changeset
1299 {
kono
parents:
diff changeset
1300 if (dump_file)
kono
parents:
diff changeset
1301 fprintf (dump_file, " Construction vtable used\n");
kono
parents:
diff changeset
1302 /* FIXME: We should suport construction contexts. */
kono
parents:
diff changeset
1303 return NULL;
kono
parents:
diff changeset
1304 }
kono
parents:
diff changeset
1305
kono
parents:
diff changeset
1306 *type_offset = tree_to_shwi (BINFO_OFFSET (binfo)) * BITS_PER_UNIT;
kono
parents:
diff changeset
1307 return DECL_CONTEXT (vtable);
kono
parents:
diff changeset
1308 }
kono
parents:
diff changeset
1309
kono
parents:
diff changeset
1310 /* Record dynamic type change of TCI to TYPE. */
kono
parents:
diff changeset
1311
kono
parents:
diff changeset
1312 static void
kono
parents:
diff changeset
1313 record_known_type (struct type_change_info *tci, tree type, HOST_WIDE_INT offset)
kono
parents:
diff changeset
1314 {
kono
parents:
diff changeset
1315 if (dump_file)
kono
parents:
diff changeset
1316 {
kono
parents:
diff changeset
1317 if (type)
kono
parents:
diff changeset
1318 {
kono
parents:
diff changeset
1319 fprintf (dump_file, " Recording type: ");
kono
parents:
diff changeset
1320 print_generic_expr (dump_file, type, TDF_SLIM);
kono
parents:
diff changeset
1321 fprintf (dump_file, " at offset %i\n", (int)offset);
kono
parents:
diff changeset
1322 }
kono
parents:
diff changeset
1323 else
kono
parents:
diff changeset
1324 fprintf (dump_file, " Recording unknown type\n");
kono
parents:
diff changeset
1325 }
kono
parents:
diff changeset
1326
kono
parents:
diff changeset
1327 /* If we found a constructor of type that is not polymorphic or
kono
parents:
diff changeset
1328 that may contain the type in question as a field (not as base),
kono
parents:
diff changeset
1329 restrict to the inner class first to make type matching bellow
kono
parents:
diff changeset
1330 happier. */
kono
parents:
diff changeset
1331 if (type
kono
parents:
diff changeset
1332 && (offset
kono
parents:
diff changeset
1333 || (TREE_CODE (type) != RECORD_TYPE
kono
parents:
diff changeset
1334 || !TYPE_BINFO (type)
kono
parents:
diff changeset
1335 || !polymorphic_type_binfo_p (TYPE_BINFO (type)))))
kono
parents:
diff changeset
1336 {
kono
parents:
diff changeset
1337 ipa_polymorphic_call_context context;
kono
parents:
diff changeset
1338
kono
parents:
diff changeset
1339 context.offset = offset;
kono
parents:
diff changeset
1340 context.outer_type = type;
kono
parents:
diff changeset
1341 context.maybe_in_construction = false;
kono
parents:
diff changeset
1342 context.maybe_derived_type = false;
kono
parents:
diff changeset
1343 context.dynamic = true;
kono
parents:
diff changeset
1344 /* If we failed to find the inner type, we know that the call
kono
parents:
diff changeset
1345 would be undefined for type produced here. */
kono
parents:
diff changeset
1346 if (!context.restrict_to_inner_class (tci->otr_type))
kono
parents:
diff changeset
1347 {
kono
parents:
diff changeset
1348 if (dump_file)
kono
parents:
diff changeset
1349 fprintf (dump_file, " Ignoring; does not contain otr_type\n");
kono
parents:
diff changeset
1350 return;
kono
parents:
diff changeset
1351 }
kono
parents:
diff changeset
1352 /* Watch for case we reached an POD type and anticipate placement
kono
parents:
diff changeset
1353 new. */
kono
parents:
diff changeset
1354 if (!context.maybe_derived_type)
kono
parents:
diff changeset
1355 {
kono
parents:
diff changeset
1356 type = context.outer_type;
kono
parents:
diff changeset
1357 offset = context.offset;
kono
parents:
diff changeset
1358 }
kono
parents:
diff changeset
1359 }
kono
parents:
diff changeset
1360 if (tci->type_maybe_changed
kono
parents:
diff changeset
1361 && (!types_same_for_odr (type, tci->known_current_type)
kono
parents:
diff changeset
1362 || offset != tci->known_current_offset))
kono
parents:
diff changeset
1363 tci->multiple_types_encountered = true;
kono
parents:
diff changeset
1364 tci->known_current_type = TYPE_MAIN_VARIANT (type);
kono
parents:
diff changeset
1365 tci->known_current_offset = offset;
kono
parents:
diff changeset
1366 tci->type_maybe_changed = true;
kono
parents:
diff changeset
1367 }
kono
parents:
diff changeset
1368
kono
parents:
diff changeset
1369
kono
parents:
diff changeset
1370 /* The maximum number of may-defs we visit when looking for a must-def
kono
parents:
diff changeset
1371 that changes the dynamic type in check_stmt_for_type_change. Tuned
kono
parents:
diff changeset
1372 after the PR12392 testcase which unlimited spends 40% time within
kono
parents:
diff changeset
1373 these alias walks and 8% with the following limit. */
kono
parents:
diff changeset
1374
kono
parents:
diff changeset
1375 static inline bool
kono
parents:
diff changeset
1376 csftc_abort_walking_p (unsigned speculative)
kono
parents:
diff changeset
1377 {
kono
parents:
diff changeset
1378 unsigned max = PARAM_VALUE (PARAM_MAX_SPECULATIVE_DEVIRT_MAYDEFS);
kono
parents:
diff changeset
1379 return speculative > max ? true : false;
kono
parents:
diff changeset
1380 }
kono
parents:
diff changeset
1381
kono
parents:
diff changeset
1382 /* Callback of walk_aliased_vdefs and a helper function for
kono
parents:
diff changeset
1383 detect_type_change to check whether a particular statement may modify
kono
parents:
diff changeset
1384 the virtual table pointer, and if possible also determine the new type of
kono
parents:
diff changeset
1385 the (sub-)object. It stores its result into DATA, which points to a
kono
parents:
diff changeset
1386 type_change_info structure. */
kono
parents:
diff changeset
1387
kono
parents:
diff changeset
1388 static bool
kono
parents:
diff changeset
1389 check_stmt_for_type_change (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef, void *data)
kono
parents:
diff changeset
1390 {
kono
parents:
diff changeset
1391 gimple *stmt = SSA_NAME_DEF_STMT (vdef);
kono
parents:
diff changeset
1392 struct type_change_info *tci = (struct type_change_info *) data;
kono
parents:
diff changeset
1393 tree fn;
kono
parents:
diff changeset
1394
kono
parents:
diff changeset
1395 /* If we already gave up, just terminate the rest of walk. */
kono
parents:
diff changeset
1396 if (tci->multiple_types_encountered)
kono
parents:
diff changeset
1397 return true;
kono
parents:
diff changeset
1398
kono
parents:
diff changeset
1399 if (is_gimple_call (stmt))
kono
parents:
diff changeset
1400 {
kono
parents:
diff changeset
1401 if (gimple_call_flags (stmt) & (ECF_CONST | ECF_PURE))
kono
parents:
diff changeset
1402 return false;
kono
parents:
diff changeset
1403
kono
parents:
diff changeset
1404 /* Check for a constructor call. */
kono
parents:
diff changeset
1405 if ((fn = gimple_call_fndecl (stmt)) != NULL_TREE
kono
parents:
diff changeset
1406 && DECL_CXX_CONSTRUCTOR_P (fn)
kono
parents:
diff changeset
1407 && TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE
kono
parents:
diff changeset
1408 && gimple_call_num_args (stmt))
kono
parents:
diff changeset
1409 {
kono
parents:
diff changeset
1410 tree op = walk_ssa_copies (gimple_call_arg (stmt, 0));
kono
parents:
diff changeset
1411 tree type = TYPE_METHOD_BASETYPE (TREE_TYPE (fn));
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1412 HOST_WIDE_INT offset = 0;
111
kono
parents:
diff changeset
1413 bool reverse;
kono
parents:
diff changeset
1414
kono
parents:
diff changeset
1415 if (dump_file)
kono
parents:
diff changeset
1416 {
kono
parents:
diff changeset
1417 fprintf (dump_file, " Checking constructor call: ");
kono
parents:
diff changeset
1418 print_gimple_stmt (dump_file, stmt, 0);
kono
parents:
diff changeset
1419 }
kono
parents:
diff changeset
1420
kono
parents:
diff changeset
1421 /* See if THIS parameter seems like instance pointer. */
kono
parents:
diff changeset
1422 if (TREE_CODE (op) == ADDR_EXPR)
kono
parents:
diff changeset
1423 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1424 HOST_WIDE_INT size;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1425 op = get_ref_base_and_extent_hwi (TREE_OPERAND (op, 0),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1426 &offset, &size, &reverse);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1427 if (!op)
111
kono
parents:
diff changeset
1428 {
kono
parents:
diff changeset
1429 tci->speculative++;
kono
parents:
diff changeset
1430 return csftc_abort_walking_p (tci->speculative);
kono
parents:
diff changeset
1431 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1432 if (TREE_CODE (op) == MEM_REF)
111
kono
parents:
diff changeset
1433 {
kono
parents:
diff changeset
1434 if (!tree_fits_shwi_p (TREE_OPERAND (op, 1)))
kono
parents:
diff changeset
1435 {
kono
parents:
diff changeset
1436 tci->speculative++;
kono
parents:
diff changeset
1437 return csftc_abort_walking_p (tci->speculative);
kono
parents:
diff changeset
1438 }
kono
parents:
diff changeset
1439 offset += tree_to_shwi (TREE_OPERAND (op, 1))
kono
parents:
diff changeset
1440 * BITS_PER_UNIT;
kono
parents:
diff changeset
1441 op = TREE_OPERAND (op, 0);
kono
parents:
diff changeset
1442 }
kono
parents:
diff changeset
1443 else if (DECL_P (op))
kono
parents:
diff changeset
1444 ;
kono
parents:
diff changeset
1445 else
kono
parents:
diff changeset
1446 {
kono
parents:
diff changeset
1447 tci->speculative++;
kono
parents:
diff changeset
1448 return csftc_abort_walking_p (tci->speculative);
kono
parents:
diff changeset
1449 }
kono
parents:
diff changeset
1450 op = walk_ssa_copies (op);
kono
parents:
diff changeset
1451 }
kono
parents:
diff changeset
1452 if (operand_equal_p (op, tci->instance, 0)
kono
parents:
diff changeset
1453 && TYPE_SIZE (type)
kono
parents:
diff changeset
1454 && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
kono
parents:
diff changeset
1455 && tree_fits_shwi_p (TYPE_SIZE (type))
kono
parents:
diff changeset
1456 && tree_to_shwi (TYPE_SIZE (type)) + offset > tci->offset
kono
parents:
diff changeset
1457 /* Some inlined constructors may look as follows:
kono
parents:
diff changeset
1458 _3 = operator new (16);
kono
parents:
diff changeset
1459 MEM[(struct &)_3] ={v} {CLOBBER};
kono
parents:
diff changeset
1460 MEM[(struct CompositeClass *)_3]._vptr.CompositeClass
kono
parents:
diff changeset
1461 = &MEM[(void *)&_ZTV14CompositeClass + 16B];
kono
parents:
diff changeset
1462 _7 = &MEM[(struct CompositeClass *)_3].object;
kono
parents:
diff changeset
1463 EmptyClass::EmptyClass (_7);
kono
parents:
diff changeset
1464
kono
parents:
diff changeset
1465 When determining dynamic type of _3 and because we stop at first
kono
parents:
diff changeset
1466 dynamic type found, we would stop on EmptyClass::EmptyClass (_7).
kono
parents:
diff changeset
1467 In this case the emptyclass is not even polymorphic and we miss
kono
parents:
diff changeset
1468 it is contained in an outer type that is polymorphic. */
kono
parents:
diff changeset
1469
kono
parents:
diff changeset
1470 && (tci->offset == offset || contains_polymorphic_type_p (type)))
kono
parents:
diff changeset
1471 {
kono
parents:
diff changeset
1472 record_known_type (tci, type, tci->offset - offset);
kono
parents:
diff changeset
1473 return true;
kono
parents:
diff changeset
1474 }
kono
parents:
diff changeset
1475 }
kono
parents:
diff changeset
1476 /* Calls may possibly change dynamic type by placement new. Assume
kono
parents:
diff changeset
1477 it will not happen, but make result speculative only. */
kono
parents:
diff changeset
1478 if (dump_file)
kono
parents:
diff changeset
1479 {
kono
parents:
diff changeset
1480 fprintf (dump_file, " Function call may change dynamic type:");
kono
parents:
diff changeset
1481 print_gimple_stmt (dump_file, stmt, 0);
kono
parents:
diff changeset
1482 }
kono
parents:
diff changeset
1483 tci->speculative++;
kono
parents:
diff changeset
1484 return csftc_abort_walking_p (tci->speculative);
kono
parents:
diff changeset
1485 }
kono
parents:
diff changeset
1486 /* Check for inlined virtual table store. */
kono
parents:
diff changeset
1487 else if (noncall_stmt_may_be_vtbl_ptr_store (stmt))
kono
parents:
diff changeset
1488 {
kono
parents:
diff changeset
1489 tree type;
kono
parents:
diff changeset
1490 HOST_WIDE_INT offset = 0;
kono
parents:
diff changeset
1491 if (dump_file)
kono
parents:
diff changeset
1492 {
kono
parents:
diff changeset
1493 fprintf (dump_file, " Checking vtbl store: ");
kono
parents:
diff changeset
1494 print_gimple_stmt (dump_file, stmt, 0);
kono
parents:
diff changeset
1495 }
kono
parents:
diff changeset
1496
kono
parents:
diff changeset
1497 type = extr_type_from_vtbl_ptr_store (stmt, tci, &offset);
kono
parents:
diff changeset
1498 if (type == error_mark_node)
kono
parents:
diff changeset
1499 return false;
kono
parents:
diff changeset
1500 gcc_assert (!type || TYPE_MAIN_VARIANT (type) == type);
kono
parents:
diff changeset
1501 if (!type)
kono
parents:
diff changeset
1502 {
kono
parents:
diff changeset
1503 if (dump_file)
kono
parents:
diff changeset
1504 fprintf (dump_file, " Unanalyzed store may change type.\n");
kono
parents:
diff changeset
1505 tci->seen_unanalyzed_store = true;
kono
parents:
diff changeset
1506 tci->speculative++;
kono
parents:
diff changeset
1507 }
kono
parents:
diff changeset
1508 else
kono
parents:
diff changeset
1509 record_known_type (tci, type, offset);
kono
parents:
diff changeset
1510 return true;
kono
parents:
diff changeset
1511 }
kono
parents:
diff changeset
1512 else
kono
parents:
diff changeset
1513 return false;
kono
parents:
diff changeset
1514 }
kono
parents:
diff changeset
1515
kono
parents:
diff changeset
1516 /* THIS is polymorphic call context obtained from get_polymorphic_context.
kono
parents:
diff changeset
1517 OTR_OBJECT is pointer to the instance returned by OBJ_TYPE_REF_OBJECT.
kono
parents:
diff changeset
1518 INSTANCE is pointer to the outer instance as returned by
kono
parents:
diff changeset
1519 get_polymorphic_context. To avoid creation of temporary expressions,
kono
parents:
diff changeset
1520 INSTANCE may also be an declaration of get_polymorphic_context found the
kono
parents:
diff changeset
1521 value to be in static storage.
kono
parents:
diff changeset
1522
kono
parents:
diff changeset
1523 If the type of instance is not fully determined
kono
parents:
diff changeset
1524 (either OUTER_TYPE is unknown or MAYBE_IN_CONSTRUCTION/INCLUDE_DERIVED_TYPES
kono
parents:
diff changeset
1525 is set), try to walk memory writes and find the actual construction of the
kono
parents:
diff changeset
1526 instance.
kono
parents:
diff changeset
1527
kono
parents:
diff changeset
1528 Return true if memory is unchanged from function entry.
kono
parents:
diff changeset
1529
kono
parents:
diff changeset
1530 We do not include this analysis in the context analysis itself, because
kono
parents:
diff changeset
1531 it needs memory SSA to be fully built and the walk may be expensive.
kono
parents:
diff changeset
1532 So it is not suitable for use withing fold_stmt and similar uses. */
kono
parents:
diff changeset
1533
kono
parents:
diff changeset
1534 bool
kono
parents:
diff changeset
1535 ipa_polymorphic_call_context::get_dynamic_type (tree instance,
kono
parents:
diff changeset
1536 tree otr_object,
kono
parents:
diff changeset
1537 tree otr_type,
kono
parents:
diff changeset
1538 gimple *call)
kono
parents:
diff changeset
1539 {
kono
parents:
diff changeset
1540 struct type_change_info tci;
kono
parents:
diff changeset
1541 ao_ref ao;
kono
parents:
diff changeset
1542 bool function_entry_reached = false;
kono
parents:
diff changeset
1543 tree instance_ref = NULL;
kono
parents:
diff changeset
1544 gimple *stmt = call;
kono
parents:
diff changeset
1545 /* Remember OFFSET before it is modified by restrict_to_inner_class.
kono
parents:
diff changeset
1546 This is because we do not update INSTANCE when walking inwards. */
kono
parents:
diff changeset
1547 HOST_WIDE_INT instance_offset = offset;
kono
parents:
diff changeset
1548 tree instance_outer_type = outer_type;
kono
parents:
diff changeset
1549
kono
parents:
diff changeset
1550 if (otr_type)
kono
parents:
diff changeset
1551 otr_type = TYPE_MAIN_VARIANT (otr_type);
kono
parents:
diff changeset
1552
kono
parents:
diff changeset
1553 /* Walk into inner type. This may clear maybe_derived_type and save us
kono
parents:
diff changeset
1554 from useless work. It also makes later comparsions with static type
kono
parents:
diff changeset
1555 easier. */
kono
parents:
diff changeset
1556 if (outer_type && otr_type)
kono
parents:
diff changeset
1557 {
kono
parents:
diff changeset
1558 if (!restrict_to_inner_class (otr_type))
kono
parents:
diff changeset
1559 return false;
kono
parents:
diff changeset
1560 }
kono
parents:
diff changeset
1561
kono
parents:
diff changeset
1562 if (!maybe_in_construction && !maybe_derived_type)
kono
parents:
diff changeset
1563 return false;
kono
parents:
diff changeset
1564
kono
parents:
diff changeset
1565 /* If we are in fact not looking at any object object or the instance is
kono
parents:
diff changeset
1566 some placement new into a random load, give up straight away. */
kono
parents:
diff changeset
1567 if (TREE_CODE (instance) == MEM_REF)
kono
parents:
diff changeset
1568 return false;
kono
parents:
diff changeset
1569
kono
parents:
diff changeset
1570 /* We need to obtain refernce to virtual table pointer. It is better
kono
parents:
diff changeset
1571 to look it up in the code rather than build our own. This require bit
kono
parents:
diff changeset
1572 of pattern matching, but we end up verifying that what we found is
kono
parents:
diff changeset
1573 correct.
kono
parents:
diff changeset
1574
kono
parents:
diff changeset
1575 What we pattern match is:
kono
parents:
diff changeset
1576
kono
parents:
diff changeset
1577 tmp = instance->_vptr.A; // vtbl ptr load
kono
parents:
diff changeset
1578 tmp2 = tmp[otr_token]; // vtable lookup
kono
parents:
diff changeset
1579 OBJ_TYPE_REF(tmp2;instance->0) (instance);
kono
parents:
diff changeset
1580
kono
parents:
diff changeset
1581 We want to start alias oracle walk from vtbl pointer load,
kono
parents:
diff changeset
1582 but we may not be able to identify it, for example, when PRE moved the
kono
parents:
diff changeset
1583 load around. */
kono
parents:
diff changeset
1584
kono
parents:
diff changeset
1585 if (gimple_code (call) == GIMPLE_CALL)
kono
parents:
diff changeset
1586 {
kono
parents:
diff changeset
1587 tree ref = gimple_call_fn (call);
kono
parents:
diff changeset
1588 bool reverse;
kono
parents:
diff changeset
1589
kono
parents:
diff changeset
1590 if (TREE_CODE (ref) == OBJ_TYPE_REF)
kono
parents:
diff changeset
1591 {
kono
parents:
diff changeset
1592 ref = OBJ_TYPE_REF_EXPR (ref);
kono
parents:
diff changeset
1593 ref = walk_ssa_copies (ref);
kono
parents:
diff changeset
1594
kono
parents:
diff changeset
1595 /* If call target is already known, no need to do the expensive
kono
parents:
diff changeset
1596 memory walk. */
kono
parents:
diff changeset
1597 if (is_gimple_min_invariant (ref))
kono
parents:
diff changeset
1598 return false;
kono
parents:
diff changeset
1599
kono
parents:
diff changeset
1600 /* Check if definition looks like vtable lookup. */
kono
parents:
diff changeset
1601 if (TREE_CODE (ref) == SSA_NAME
kono
parents:
diff changeset
1602 && !SSA_NAME_IS_DEFAULT_DEF (ref)
kono
parents:
diff changeset
1603 && gimple_assign_load_p (SSA_NAME_DEF_STMT (ref))
kono
parents:
diff changeset
1604 && TREE_CODE (gimple_assign_rhs1
kono
parents:
diff changeset
1605 (SSA_NAME_DEF_STMT (ref))) == MEM_REF)
kono
parents:
diff changeset
1606 {
kono
parents:
diff changeset
1607 ref = get_base_address
kono
parents:
diff changeset
1608 (TREE_OPERAND (gimple_assign_rhs1
kono
parents:
diff changeset
1609 (SSA_NAME_DEF_STMT (ref)), 0));
kono
parents:
diff changeset
1610 ref = walk_ssa_copies (ref);
kono
parents:
diff changeset
1611 /* Find base address of the lookup and see if it looks like
kono
parents:
diff changeset
1612 vptr load. */
kono
parents:
diff changeset
1613 if (TREE_CODE (ref) == SSA_NAME
kono
parents:
diff changeset
1614 && !SSA_NAME_IS_DEFAULT_DEF (ref)
kono
parents:
diff changeset
1615 && gimple_assign_load_p (SSA_NAME_DEF_STMT (ref)))
kono
parents:
diff changeset
1616 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1617 HOST_WIDE_INT offset2, size;
111
kono
parents:
diff changeset
1618 tree ref_exp = gimple_assign_rhs1 (SSA_NAME_DEF_STMT (ref));
kono
parents:
diff changeset
1619 tree base_ref
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1620 = get_ref_base_and_extent_hwi (ref_exp, &offset2,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1621 &size, &reverse);
111
kono
parents:
diff changeset
1622
kono
parents:
diff changeset
1623 /* Finally verify that what we found looks like read from
kono
parents:
diff changeset
1624 OTR_OBJECT or from INSTANCE with offset OFFSET. */
kono
parents:
diff changeset
1625 if (base_ref
kono
parents:
diff changeset
1626 && ((TREE_CODE (base_ref) == MEM_REF
kono
parents:
diff changeset
1627 && ((offset2 == instance_offset
kono
parents:
diff changeset
1628 && TREE_OPERAND (base_ref, 0) == instance)
kono
parents:
diff changeset
1629 || (!offset2
kono
parents:
diff changeset
1630 && TREE_OPERAND (base_ref, 0)
kono
parents:
diff changeset
1631 == otr_object)))
kono
parents:
diff changeset
1632 || (DECL_P (instance) && base_ref == instance
kono
parents:
diff changeset
1633 && offset2 == instance_offset)))
kono
parents:
diff changeset
1634 {
kono
parents:
diff changeset
1635 stmt = SSA_NAME_DEF_STMT (ref);
kono
parents:
diff changeset
1636 instance_ref = ref_exp;
kono
parents:
diff changeset
1637 }
kono
parents:
diff changeset
1638 }
kono
parents:
diff changeset
1639 }
kono
parents:
diff changeset
1640 }
kono
parents:
diff changeset
1641 }
kono
parents:
diff changeset
1642
kono
parents:
diff changeset
1643 /* If we failed to look up the reference in code, build our own. */
kono
parents:
diff changeset
1644 if (!instance_ref)
kono
parents:
diff changeset
1645 {
kono
parents:
diff changeset
1646 /* If the statement in question does not use memory, we can't tell
kono
parents:
diff changeset
1647 anything. */
kono
parents:
diff changeset
1648 if (!gimple_vuse (stmt))
kono
parents:
diff changeset
1649 return false;
kono
parents:
diff changeset
1650 ao_ref_init_from_ptr_and_size (&ao, otr_object, NULL);
kono
parents:
diff changeset
1651 }
kono
parents:
diff changeset
1652 else
kono
parents:
diff changeset
1653 /* Otherwise use the real reference. */
kono
parents:
diff changeset
1654 ao_ref_init (&ao, instance_ref);
kono
parents:
diff changeset
1655
kono
parents:
diff changeset
1656 /* We look for vtbl pointer read. */
kono
parents:
diff changeset
1657 ao.size = POINTER_SIZE;
kono
parents:
diff changeset
1658 ao.max_size = ao.size;
kono
parents:
diff changeset
1659 /* We are looking for stores to vptr pointer within the instance of
kono
parents:
diff changeset
1660 outer type.
kono
parents:
diff changeset
1661 TODO: The vptr pointer type is globally known, we probably should
kono
parents:
diff changeset
1662 keep it and do that even when otr_type is unknown. */
kono
parents:
diff changeset
1663 if (otr_type)
kono
parents:
diff changeset
1664 {
kono
parents:
diff changeset
1665 ao.base_alias_set
kono
parents:
diff changeset
1666 = get_alias_set (outer_type ? outer_type : otr_type);
kono
parents:
diff changeset
1667 ao.ref_alias_set
kono
parents:
diff changeset
1668 = get_alias_set (TREE_TYPE (BINFO_VTABLE (TYPE_BINFO (otr_type))));
kono
parents:
diff changeset
1669 }
kono
parents:
diff changeset
1670
kono
parents:
diff changeset
1671 if (dump_file)
kono
parents:
diff changeset
1672 {
kono
parents:
diff changeset
1673 fprintf (dump_file, "Determining dynamic type for call: ");
kono
parents:
diff changeset
1674 print_gimple_stmt (dump_file, call, 0);
kono
parents:
diff changeset
1675 fprintf (dump_file, " Starting walk at: ");
kono
parents:
diff changeset
1676 print_gimple_stmt (dump_file, stmt, 0);
kono
parents:
diff changeset
1677 fprintf (dump_file, " instance pointer: ");
kono
parents:
diff changeset
1678 print_generic_expr (dump_file, otr_object, TDF_SLIM);
kono
parents:
diff changeset
1679 fprintf (dump_file, " Outer instance pointer: ");
kono
parents:
diff changeset
1680 print_generic_expr (dump_file, instance, TDF_SLIM);
kono
parents:
diff changeset
1681 fprintf (dump_file, " offset: %i (bits)", (int)instance_offset);
kono
parents:
diff changeset
1682 fprintf (dump_file, " vtbl reference: ");
kono
parents:
diff changeset
1683 print_generic_expr (dump_file, instance_ref, TDF_SLIM);
kono
parents:
diff changeset
1684 fprintf (dump_file, "\n");
kono
parents:
diff changeset
1685 }
kono
parents:
diff changeset
1686
kono
parents:
diff changeset
1687 tci.offset = instance_offset;
kono
parents:
diff changeset
1688 tci.instance = instance;
kono
parents:
diff changeset
1689 tci.vtbl_ptr_ref = instance_ref;
kono
parents:
diff changeset
1690 tci.known_current_type = NULL_TREE;
kono
parents:
diff changeset
1691 tci.known_current_offset = 0;
kono
parents:
diff changeset
1692 tci.otr_type = otr_type;
kono
parents:
diff changeset
1693 tci.type_maybe_changed = false;
kono
parents:
diff changeset
1694 tci.multiple_types_encountered = false;
kono
parents:
diff changeset
1695 tci.speculative = 0;
kono
parents:
diff changeset
1696 tci.seen_unanalyzed_store = false;
kono
parents:
diff changeset
1697
kono
parents:
diff changeset
1698 walk_aliased_vdefs (&ao, gimple_vuse (stmt), check_stmt_for_type_change,
kono
parents:
diff changeset
1699 &tci, NULL, &function_entry_reached);
kono
parents:
diff changeset
1700
kono
parents:
diff changeset
1701 /* If we did not find any type changing statements, we may still drop
kono
parents:
diff changeset
1702 maybe_in_construction flag if the context already have outer type.
kono
parents:
diff changeset
1703
kono
parents:
diff changeset
1704 Here we make special assumptions about both constructors and
kono
parents:
diff changeset
1705 destructors which are all the functions that are allowed to alter the
kono
parents:
diff changeset
1706 VMT pointers. It assumes that destructors begin with assignment into
kono
parents:
diff changeset
1707 all VMT pointers and that constructors essentially look in the
kono
parents:
diff changeset
1708 following way:
kono
parents:
diff changeset
1709
kono
parents:
diff changeset
1710 1) The very first thing they do is that they call constructors of
kono
parents:
diff changeset
1711 ancestor sub-objects that have them.
kono
parents:
diff changeset
1712
kono
parents:
diff changeset
1713 2) Then VMT pointers of this and all its ancestors is set to new
kono
parents:
diff changeset
1714 values corresponding to the type corresponding to the constructor.
kono
parents:
diff changeset
1715
kono
parents:
diff changeset
1716 3) Only afterwards, other stuff such as constructor of member
kono
parents:
diff changeset
1717 sub-objects and the code written by the user is run. Only this may
kono
parents:
diff changeset
1718 include calling virtual functions, directly or indirectly.
kono
parents:
diff changeset
1719
kono
parents:
diff changeset
1720 4) placement new can not be used to change type of non-POD statically
kono
parents:
diff changeset
1721 allocated variables.
kono
parents:
diff changeset
1722
kono
parents:
diff changeset
1723 There is no way to call a constructor of an ancestor sub-object in any
kono
parents:
diff changeset
1724 other way.
kono
parents:
diff changeset
1725
kono
parents:
diff changeset
1726 This means that we do not have to care whether constructors get the
kono
parents:
diff changeset
1727 correct type information because they will always change it (in fact,
kono
parents:
diff changeset
1728 if we define the type to be given by the VMT pointer, it is undefined).
kono
parents:
diff changeset
1729
kono
parents:
diff changeset
1730 The most important fact to derive from the above is that if, for some
kono
parents:
diff changeset
1731 statement in the section 3, we try to detect whether the dynamic type
kono
parents:
diff changeset
1732 has changed, we can safely ignore all calls as we examine the function
kono
parents:
diff changeset
1733 body backwards until we reach statements in section 2 because these
kono
parents:
diff changeset
1734 calls cannot be ancestor constructors or destructors (if the input is
kono
parents:
diff changeset
1735 not bogus) and so do not change the dynamic type (this holds true only
kono
parents:
diff changeset
1736 for automatically allocated objects but at the moment we devirtualize
kono
parents:
diff changeset
1737 only these). We then must detect that statements in section 2 change
kono
parents:
diff changeset
1738 the dynamic type and can try to derive the new type. That is enough
kono
parents:
diff changeset
1739 and we can stop, we will never see the calls into constructors of
kono
parents:
diff changeset
1740 sub-objects in this code.
kono
parents:
diff changeset
1741
kono
parents:
diff changeset
1742 Therefore if the static outer type was found (outer_type)
kono
parents:
diff changeset
1743 we can safely ignore tci.speculative that is set on calls and give up
kono
parents:
diff changeset
1744 only if there was dyanmic type store that may affect given variable
kono
parents:
diff changeset
1745 (seen_unanalyzed_store) */
kono
parents:
diff changeset
1746
kono
parents:
diff changeset
1747 if (!tci.type_maybe_changed
kono
parents:
diff changeset
1748 || (outer_type
kono
parents:
diff changeset
1749 && !dynamic
kono
parents:
diff changeset
1750 && !tci.seen_unanalyzed_store
kono
parents:
diff changeset
1751 && !tci.multiple_types_encountered
kono
parents:
diff changeset
1752 && ((offset == tci.offset
kono
parents:
diff changeset
1753 && types_same_for_odr (tci.known_current_type,
kono
parents:
diff changeset
1754 outer_type))
kono
parents:
diff changeset
1755 || (instance_offset == offset
kono
parents:
diff changeset
1756 && types_same_for_odr (tci.known_current_type,
kono
parents:
diff changeset
1757 instance_outer_type)))))
kono
parents:
diff changeset
1758 {
kono
parents:
diff changeset
1759 if (!outer_type || tci.seen_unanalyzed_store)
kono
parents:
diff changeset
1760 return false;
kono
parents:
diff changeset
1761 if (maybe_in_construction)
kono
parents:
diff changeset
1762 maybe_in_construction = false;
kono
parents:
diff changeset
1763 if (dump_file)
kono
parents:
diff changeset
1764 fprintf (dump_file, " No dynamic type change found.\n");
kono
parents:
diff changeset
1765 return true;
kono
parents:
diff changeset
1766 }
kono
parents:
diff changeset
1767
kono
parents:
diff changeset
1768 if (tci.known_current_type
kono
parents:
diff changeset
1769 && !function_entry_reached
kono
parents:
diff changeset
1770 && !tci.multiple_types_encountered)
kono
parents:
diff changeset
1771 {
kono
parents:
diff changeset
1772 if (!tci.speculative)
kono
parents:
diff changeset
1773 {
kono
parents:
diff changeset
1774 outer_type = TYPE_MAIN_VARIANT (tci.known_current_type);
kono
parents:
diff changeset
1775 offset = tci.known_current_offset;
kono
parents:
diff changeset
1776 dynamic = true;
kono
parents:
diff changeset
1777 maybe_in_construction = false;
kono
parents:
diff changeset
1778 maybe_derived_type = false;
kono
parents:
diff changeset
1779 if (dump_file)
kono
parents:
diff changeset
1780 fprintf (dump_file, " Determined dynamic type.\n");
kono
parents:
diff changeset
1781 }
kono
parents:
diff changeset
1782 else if (!speculative_outer_type
kono
parents:
diff changeset
1783 || speculative_maybe_derived_type)
kono
parents:
diff changeset
1784 {
kono
parents:
diff changeset
1785 speculative_outer_type = TYPE_MAIN_VARIANT (tci.known_current_type);
kono
parents:
diff changeset
1786 speculative_offset = tci.known_current_offset;
kono
parents:
diff changeset
1787 speculative_maybe_derived_type = false;
kono
parents:
diff changeset
1788 if (dump_file)
kono
parents:
diff changeset
1789 fprintf (dump_file, " Determined speculative dynamic type.\n");
kono
parents:
diff changeset
1790 }
kono
parents:
diff changeset
1791 }
kono
parents:
diff changeset
1792 else if (dump_file)
kono
parents:
diff changeset
1793 {
kono
parents:
diff changeset
1794 fprintf (dump_file, " Found multiple types%s%s\n",
kono
parents:
diff changeset
1795 function_entry_reached ? " (function entry reached)" : "",
kono
parents:
diff changeset
1796 function_entry_reached ? " (multiple types encountered)" : "");
kono
parents:
diff changeset
1797 }
kono
parents:
diff changeset
1798
kono
parents:
diff changeset
1799 return false;
kono
parents:
diff changeset
1800 }
kono
parents:
diff changeset
1801
kono
parents:
diff changeset
1802 /* See if speculation given by SPEC_OUTER_TYPE, SPEC_OFFSET and SPEC_MAYBE_DERIVED_TYPE
kono
parents:
diff changeset
1803 seems consistent (and useful) with what we already have in the non-speculative context. */
kono
parents:
diff changeset
1804
kono
parents:
diff changeset
1805 bool
kono
parents:
diff changeset
1806 ipa_polymorphic_call_context::speculation_consistent_p (tree spec_outer_type,
kono
parents:
diff changeset
1807 HOST_WIDE_INT spec_offset,
kono
parents:
diff changeset
1808 bool spec_maybe_derived_type,
kono
parents:
diff changeset
1809 tree otr_type) const
kono
parents:
diff changeset
1810 {
kono
parents:
diff changeset
1811 if (!flag_devirtualize_speculatively)
kono
parents:
diff changeset
1812 return false;
kono
parents:
diff changeset
1813
kono
parents:
diff changeset
1814 /* Non-polymorphic types are useless for deriving likely polymorphic
kono
parents:
diff changeset
1815 call targets. */
kono
parents:
diff changeset
1816 if (!spec_outer_type || !contains_polymorphic_type_p (spec_outer_type))
kono
parents:
diff changeset
1817 return false;
kono
parents:
diff changeset
1818
kono
parents:
diff changeset
1819 /* If we know nothing, speculation is always good. */
kono
parents:
diff changeset
1820 if (!outer_type)
kono
parents:
diff changeset
1821 return true;
kono
parents:
diff changeset
1822
kono
parents:
diff changeset
1823 /* Speculation is only useful to avoid derived types.
kono
parents:
diff changeset
1824 This is not 100% true for placement new, where the outer context may
kono
parents:
diff changeset
1825 turn out to be useless, but ignore these for now. */
kono
parents:
diff changeset
1826 if (!maybe_derived_type)
kono
parents:
diff changeset
1827 return false;
kono
parents:
diff changeset
1828
kono
parents:
diff changeset
1829 /* If types agrees, speculation is consistent, but it makes sense only
kono
parents:
diff changeset
1830 when it says something new. */
kono
parents:
diff changeset
1831 if (types_must_be_same_for_odr (spec_outer_type, outer_type))
kono
parents:
diff changeset
1832 return maybe_derived_type && !spec_maybe_derived_type;
kono
parents:
diff changeset
1833
kono
parents:
diff changeset
1834 /* If speculation does not contain the type in question, ignore it. */
kono
parents:
diff changeset
1835 if (otr_type
kono
parents:
diff changeset
1836 && !contains_type_p (spec_outer_type, spec_offset, otr_type, false, true))
kono
parents:
diff changeset
1837 return false;
kono
parents:
diff changeset
1838
kono
parents:
diff changeset
1839 /* If outer type already contains speculation as a filed,
kono
parents:
diff changeset
1840 it is useless. We already know from OUTER_TYPE
kono
parents:
diff changeset
1841 SPEC_TYPE and that it is not in the construction. */
kono
parents:
diff changeset
1842 if (contains_type_p (outer_type, offset - spec_offset,
kono
parents:
diff changeset
1843 spec_outer_type, false, false))
kono
parents:
diff changeset
1844 return false;
kono
parents:
diff changeset
1845
kono
parents:
diff changeset
1846 /* If speculative outer type is not more specified than outer
kono
parents:
diff changeset
1847 type, just give up.
kono
parents:
diff changeset
1848 We can only decide this safely if we can compare types with OUTER_TYPE.
kono
parents:
diff changeset
1849 */
kono
parents:
diff changeset
1850 if ((!in_lto_p || odr_type_p (outer_type))
kono
parents:
diff changeset
1851 && !contains_type_p (spec_outer_type,
kono
parents:
diff changeset
1852 spec_offset - offset,
kono
parents:
diff changeset
1853 outer_type, false))
kono
parents:
diff changeset
1854 return false;
kono
parents:
diff changeset
1855 return true;
kono
parents:
diff changeset
1856 }
kono
parents:
diff changeset
1857
kono
parents:
diff changeset
1858 /* Improve THIS with speculation described by NEW_OUTER_TYPE, NEW_OFFSET,
kono
parents:
diff changeset
1859 NEW_MAYBE_DERIVED_TYPE
kono
parents:
diff changeset
1860 If OTR_TYPE is set, assume the context is used with OTR_TYPE. */
kono
parents:
diff changeset
1861
kono
parents:
diff changeset
1862 bool
kono
parents:
diff changeset
1863 ipa_polymorphic_call_context::combine_speculation_with
kono
parents:
diff changeset
1864 (tree new_outer_type, HOST_WIDE_INT new_offset, bool new_maybe_derived_type,
kono
parents:
diff changeset
1865 tree otr_type)
kono
parents:
diff changeset
1866 {
kono
parents:
diff changeset
1867 if (!new_outer_type)
kono
parents:
diff changeset
1868 return false;
kono
parents:
diff changeset
1869
kono
parents:
diff changeset
1870 /* restrict_to_inner_class may eliminate wrong speculation making our job
kono
parents:
diff changeset
1871 easeier. */
kono
parents:
diff changeset
1872 if (otr_type)
kono
parents:
diff changeset
1873 restrict_to_inner_class (otr_type);
kono
parents:
diff changeset
1874
kono
parents:
diff changeset
1875 if (!speculation_consistent_p (new_outer_type, new_offset,
kono
parents:
diff changeset
1876 new_maybe_derived_type, otr_type))
kono
parents:
diff changeset
1877 return false;
kono
parents:
diff changeset
1878
kono
parents:
diff changeset
1879 /* New speculation is a win in case we have no speculation or new
kono
parents:
diff changeset
1880 speculation does not consider derivations. */
kono
parents:
diff changeset
1881 if (!speculative_outer_type
kono
parents:
diff changeset
1882 || (speculative_maybe_derived_type
kono
parents:
diff changeset
1883 && !new_maybe_derived_type))
kono
parents:
diff changeset
1884 {
kono
parents:
diff changeset
1885 speculative_outer_type = new_outer_type;
kono
parents:
diff changeset
1886 speculative_offset = new_offset;
kono
parents:
diff changeset
1887 speculative_maybe_derived_type = new_maybe_derived_type;
kono
parents:
diff changeset
1888 return true;
kono
parents:
diff changeset
1889 }
kono
parents:
diff changeset
1890 else if (types_must_be_same_for_odr (speculative_outer_type,
kono
parents:
diff changeset
1891 new_outer_type))
kono
parents:
diff changeset
1892 {
kono
parents:
diff changeset
1893 if (speculative_offset != new_offset)
kono
parents:
diff changeset
1894 {
kono
parents:
diff changeset
1895 /* OK we have two contexts that seems valid but they disagree,
kono
parents:
diff changeset
1896 just give up.
kono
parents:
diff changeset
1897
kono
parents:
diff changeset
1898 This is not a lattice operation, so we may want to drop it later. */
kono
parents:
diff changeset
1899 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
1900 fprintf (dump_file,
kono
parents:
diff changeset
1901 "Speculative outer types match, "
kono
parents:
diff changeset
1902 "offset mismatch -> invalid speculation\n");
kono
parents:
diff changeset
1903 clear_speculation ();
kono
parents:
diff changeset
1904 return true;
kono
parents:
diff changeset
1905 }
kono
parents:
diff changeset
1906 else
kono
parents:
diff changeset
1907 {
kono
parents:
diff changeset
1908 if (speculative_maybe_derived_type && !new_maybe_derived_type)
kono
parents:
diff changeset
1909 {
kono
parents:
diff changeset
1910 speculative_maybe_derived_type = false;
kono
parents:
diff changeset
1911 return true;
kono
parents:
diff changeset
1912 }
kono
parents:
diff changeset
1913 else
kono
parents:
diff changeset
1914 return false;
kono
parents:
diff changeset
1915 }
kono
parents:
diff changeset
1916 }
kono
parents:
diff changeset
1917 /* Choose type that contains the other. This one either contains the outer
kono
parents:
diff changeset
1918 as a field (thus giving exactly one target) or is deeper in the type
kono
parents:
diff changeset
1919 hiearchy. */
kono
parents:
diff changeset
1920 else if (speculative_outer_type
kono
parents:
diff changeset
1921 && speculative_maybe_derived_type
kono
parents:
diff changeset
1922 && (new_offset > speculative_offset
kono
parents:
diff changeset
1923 || (new_offset == speculative_offset
kono
parents:
diff changeset
1924 && contains_type_p (new_outer_type,
kono
parents:
diff changeset
1925 0, speculative_outer_type, false))))
kono
parents:
diff changeset
1926 {
kono
parents:
diff changeset
1927 tree old_outer_type = speculative_outer_type;
kono
parents:
diff changeset
1928 HOST_WIDE_INT old_offset = speculative_offset;
kono
parents:
diff changeset
1929 bool old_maybe_derived_type = speculative_maybe_derived_type;
kono
parents:
diff changeset
1930
kono
parents:
diff changeset
1931 speculative_outer_type = new_outer_type;
kono
parents:
diff changeset
1932 speculative_offset = new_offset;
kono
parents:
diff changeset
1933 speculative_maybe_derived_type = new_maybe_derived_type;
kono
parents:
diff changeset
1934
kono
parents:
diff changeset
1935 if (otr_type)
kono
parents:
diff changeset
1936 restrict_to_inner_class (otr_type);
kono
parents:
diff changeset
1937
kono
parents:
diff changeset
1938 /* If the speculation turned out to make no sense, revert to sensible
kono
parents:
diff changeset
1939 one. */
kono
parents:
diff changeset
1940 if (!speculative_outer_type)
kono
parents:
diff changeset
1941 {
kono
parents:
diff changeset
1942 speculative_outer_type = old_outer_type;
kono
parents:
diff changeset
1943 speculative_offset = old_offset;
kono
parents:
diff changeset
1944 speculative_maybe_derived_type = old_maybe_derived_type;
kono
parents:
diff changeset
1945 return false;
kono
parents:
diff changeset
1946 }
kono
parents:
diff changeset
1947 return (old_offset != speculative_offset
kono
parents:
diff changeset
1948 || old_maybe_derived_type != speculative_maybe_derived_type
kono
parents:
diff changeset
1949 || types_must_be_same_for_odr (speculative_outer_type,
kono
parents:
diff changeset
1950 new_outer_type));
kono
parents:
diff changeset
1951 }
kono
parents:
diff changeset
1952 return false;
kono
parents:
diff changeset
1953 }
kono
parents:
diff changeset
1954
kono
parents:
diff changeset
1955 /* Make speculation less specific so
kono
parents:
diff changeset
1956 NEW_OUTER_TYPE, NEW_OFFSET, NEW_MAYBE_DERIVED_TYPE is also included.
kono
parents:
diff changeset
1957 If OTR_TYPE is set, assume the context is used with OTR_TYPE. */
kono
parents:
diff changeset
1958
kono
parents:
diff changeset
1959 bool
kono
parents:
diff changeset
1960 ipa_polymorphic_call_context::meet_speculation_with
kono
parents:
diff changeset
1961 (tree new_outer_type, HOST_WIDE_INT new_offset, bool new_maybe_derived_type,
kono
parents:
diff changeset
1962 tree otr_type)
kono
parents:
diff changeset
1963 {
kono
parents:
diff changeset
1964 if (!new_outer_type && speculative_outer_type)
kono
parents:
diff changeset
1965 {
kono
parents:
diff changeset
1966 clear_speculation ();
kono
parents:
diff changeset
1967 return true;
kono
parents:
diff changeset
1968 }
kono
parents:
diff changeset
1969
kono
parents:
diff changeset
1970 /* restrict_to_inner_class may eliminate wrong speculation making our job
kono
parents:
diff changeset
1971 easeier. */
kono
parents:
diff changeset
1972 if (otr_type)
kono
parents:
diff changeset
1973 restrict_to_inner_class (otr_type);
kono
parents:
diff changeset
1974
kono
parents:
diff changeset
1975 if (!speculative_outer_type
kono
parents:
diff changeset
1976 || !speculation_consistent_p (speculative_outer_type,
kono
parents:
diff changeset
1977 speculative_offset,
kono
parents:
diff changeset
1978 speculative_maybe_derived_type,
kono
parents:
diff changeset
1979 otr_type))
kono
parents:
diff changeset
1980 return false;
kono
parents:
diff changeset
1981
kono
parents:
diff changeset
1982 if (!speculation_consistent_p (new_outer_type, new_offset,
kono
parents:
diff changeset
1983 new_maybe_derived_type, otr_type))
kono
parents:
diff changeset
1984 {
kono
parents:
diff changeset
1985 clear_speculation ();
kono
parents:
diff changeset
1986 return true;
kono
parents:
diff changeset
1987 }
kono
parents:
diff changeset
1988
kono
parents:
diff changeset
1989 else if (types_must_be_same_for_odr (speculative_outer_type,
kono
parents:
diff changeset
1990 new_outer_type))
kono
parents:
diff changeset
1991 {
kono
parents:
diff changeset
1992 if (speculative_offset != new_offset)
kono
parents:
diff changeset
1993 {
kono
parents:
diff changeset
1994 clear_speculation ();
kono
parents:
diff changeset
1995 return true;
kono
parents:
diff changeset
1996 }
kono
parents:
diff changeset
1997 else
kono
parents:
diff changeset
1998 {
kono
parents:
diff changeset
1999 if (!speculative_maybe_derived_type && new_maybe_derived_type)
kono
parents:
diff changeset
2000 {
kono
parents:
diff changeset
2001 speculative_maybe_derived_type = true;
kono
parents:
diff changeset
2002 return true;
kono
parents:
diff changeset
2003 }
kono
parents:
diff changeset
2004 else
kono
parents:
diff changeset
2005 return false;
kono
parents:
diff changeset
2006 }
kono
parents:
diff changeset
2007 }
kono
parents:
diff changeset
2008 /* See if one type contains the other as a field (not base). */
kono
parents:
diff changeset
2009 else if (contains_type_p (new_outer_type, new_offset - speculative_offset,
kono
parents:
diff changeset
2010 speculative_outer_type, false, false))
kono
parents:
diff changeset
2011 return false;
kono
parents:
diff changeset
2012 else if (contains_type_p (speculative_outer_type,
kono
parents:
diff changeset
2013 speculative_offset - new_offset,
kono
parents:
diff changeset
2014 new_outer_type, false, false))
kono
parents:
diff changeset
2015 {
kono
parents:
diff changeset
2016 speculative_outer_type = new_outer_type;
kono
parents:
diff changeset
2017 speculative_offset = new_offset;
kono
parents:
diff changeset
2018 speculative_maybe_derived_type = new_maybe_derived_type;
kono
parents:
diff changeset
2019 return true;
kono
parents:
diff changeset
2020 }
kono
parents:
diff changeset
2021 /* See if OUTER_TYPE is base of CTX.OUTER_TYPE. */
kono
parents:
diff changeset
2022 else if (contains_type_p (new_outer_type,
kono
parents:
diff changeset
2023 new_offset - speculative_offset,
kono
parents:
diff changeset
2024 speculative_outer_type, false, true))
kono
parents:
diff changeset
2025 {
kono
parents:
diff changeset
2026 if (!speculative_maybe_derived_type)
kono
parents:
diff changeset
2027 {
kono
parents:
diff changeset
2028 speculative_maybe_derived_type = true;
kono
parents:
diff changeset
2029 return true;
kono
parents:
diff changeset
2030 }
kono
parents:
diff changeset
2031 return false;
kono
parents:
diff changeset
2032 }
kono
parents:
diff changeset
2033 /* See if CTX.OUTER_TYPE is base of OUTER_TYPE. */
kono
parents:
diff changeset
2034 else if (contains_type_p (speculative_outer_type,
kono
parents:
diff changeset
2035 speculative_offset - new_offset, new_outer_type, false, true))
kono
parents:
diff changeset
2036 {
kono
parents:
diff changeset
2037 speculative_outer_type = new_outer_type;
kono
parents:
diff changeset
2038 speculative_offset = new_offset;
kono
parents:
diff changeset
2039 speculative_maybe_derived_type = true;
kono
parents:
diff changeset
2040 return true;
kono
parents:
diff changeset
2041 }
kono
parents:
diff changeset
2042 else
kono
parents:
diff changeset
2043 {
kono
parents:
diff changeset
2044 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2045 fprintf (dump_file, "Giving up on speculative meet\n");
kono
parents:
diff changeset
2046 clear_speculation ();
kono
parents:
diff changeset
2047 return true;
kono
parents:
diff changeset
2048 }
kono
parents:
diff changeset
2049 }
kono
parents:
diff changeset
2050
kono
parents:
diff changeset
2051 /* Assume that both THIS and a given context is valid and strenghten THIS
kono
parents:
diff changeset
2052 if possible. Return true if any strenghtening was made.
kono
parents:
diff changeset
2053 If actual type the context is being used in is known, OTR_TYPE should be
kono
parents:
diff changeset
2054 set accordingly. This improves quality of combined result. */
kono
parents:
diff changeset
2055
kono
parents:
diff changeset
2056 bool
kono
parents:
diff changeset
2057 ipa_polymorphic_call_context::combine_with (ipa_polymorphic_call_context ctx,
kono
parents:
diff changeset
2058 tree otr_type)
kono
parents:
diff changeset
2059 {
kono
parents:
diff changeset
2060 bool updated = false;
kono
parents:
diff changeset
2061
kono
parents:
diff changeset
2062 if (ctx.useless_p () || invalid)
kono
parents:
diff changeset
2063 return false;
kono
parents:
diff changeset
2064
kono
parents:
diff changeset
2065 /* Restricting context to inner type makes merging easier, however do not
kono
parents:
diff changeset
2066 do that unless we know how the context is used (OTR_TYPE is non-NULL) */
kono
parents:
diff changeset
2067 if (otr_type && !invalid && !ctx.invalid)
kono
parents:
diff changeset
2068 {
kono
parents:
diff changeset
2069 restrict_to_inner_class (otr_type);
kono
parents:
diff changeset
2070 ctx.restrict_to_inner_class (otr_type);
kono
parents:
diff changeset
2071 if(invalid)
kono
parents:
diff changeset
2072 return false;
kono
parents:
diff changeset
2073 }
kono
parents:
diff changeset
2074
kono
parents:
diff changeset
2075 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2076 {
kono
parents:
diff changeset
2077 fprintf (dump_file, "Polymorphic call context combine:");
kono
parents:
diff changeset
2078 dump (dump_file);
kono
parents:
diff changeset
2079 fprintf (dump_file, "With context: ");
kono
parents:
diff changeset
2080 ctx.dump (dump_file);
kono
parents:
diff changeset
2081 if (otr_type)
kono
parents:
diff changeset
2082 {
kono
parents:
diff changeset
2083 fprintf (dump_file, "To be used with type: ");
kono
parents:
diff changeset
2084 print_generic_expr (dump_file, otr_type, TDF_SLIM);
kono
parents:
diff changeset
2085 fprintf (dump_file, "\n");
kono
parents:
diff changeset
2086 }
kono
parents:
diff changeset
2087 }
kono
parents:
diff changeset
2088
kono
parents:
diff changeset
2089 /* If call is known to be invalid, we are done. */
kono
parents:
diff changeset
2090 if (ctx.invalid)
kono
parents:
diff changeset
2091 {
kono
parents:
diff changeset
2092 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2093 fprintf (dump_file, "-> Invalid context\n");
kono
parents:
diff changeset
2094 goto invalidate;
kono
parents:
diff changeset
2095 }
kono
parents:
diff changeset
2096
kono
parents:
diff changeset
2097 if (!ctx.outer_type)
kono
parents:
diff changeset
2098 ;
kono
parents:
diff changeset
2099 else if (!outer_type)
kono
parents:
diff changeset
2100 {
kono
parents:
diff changeset
2101 outer_type = ctx.outer_type;
kono
parents:
diff changeset
2102 offset = ctx.offset;
kono
parents:
diff changeset
2103 dynamic = ctx.dynamic;
kono
parents:
diff changeset
2104 maybe_in_construction = ctx.maybe_in_construction;
kono
parents:
diff changeset
2105 maybe_derived_type = ctx.maybe_derived_type;
kono
parents:
diff changeset
2106 updated = true;
kono
parents:
diff changeset
2107 }
kono
parents:
diff changeset
2108 /* If types are known to be same, merging is quite easy. */
kono
parents:
diff changeset
2109 else if (types_must_be_same_for_odr (outer_type, ctx.outer_type))
kono
parents:
diff changeset
2110 {
kono
parents:
diff changeset
2111 if (offset != ctx.offset
kono
parents:
diff changeset
2112 && TYPE_SIZE (outer_type)
kono
parents:
diff changeset
2113 && TREE_CODE (TYPE_SIZE (outer_type)) == INTEGER_CST)
kono
parents:
diff changeset
2114 {
kono
parents:
diff changeset
2115 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2116 fprintf (dump_file, "Outer types match, offset mismatch -> invalid\n");
kono
parents:
diff changeset
2117 clear_speculation ();
kono
parents:
diff changeset
2118 clear_outer_type ();
kono
parents:
diff changeset
2119 invalid = true;
kono
parents:
diff changeset
2120 return true;
kono
parents:
diff changeset
2121 }
kono
parents:
diff changeset
2122 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2123 fprintf (dump_file, "Outer types match, merging flags\n");
kono
parents:
diff changeset
2124 if (maybe_in_construction && !ctx.maybe_in_construction)
kono
parents:
diff changeset
2125 {
kono
parents:
diff changeset
2126 updated = true;
kono
parents:
diff changeset
2127 maybe_in_construction = false;
kono
parents:
diff changeset
2128 }
kono
parents:
diff changeset
2129 if (maybe_derived_type && !ctx.maybe_derived_type)
kono
parents:
diff changeset
2130 {
kono
parents:
diff changeset
2131 updated = true;
kono
parents:
diff changeset
2132 maybe_derived_type = false;
kono
parents:
diff changeset
2133 }
kono
parents:
diff changeset
2134 if (dynamic && !ctx.dynamic)
kono
parents:
diff changeset
2135 {
kono
parents:
diff changeset
2136 updated = true;
kono
parents:
diff changeset
2137 dynamic = false;
kono
parents:
diff changeset
2138 }
kono
parents:
diff changeset
2139 }
kono
parents:
diff changeset
2140 /* If we know the type precisely, there is not much to improve. */
kono
parents:
diff changeset
2141 else if (!maybe_derived_type && !maybe_in_construction
kono
parents:
diff changeset
2142 && !ctx.maybe_derived_type && !ctx.maybe_in_construction)
kono
parents:
diff changeset
2143 {
kono
parents:
diff changeset
2144 /* It may be easy to check if second context permits the first
kono
parents:
diff changeset
2145 and set INVALID otherwise. This is not easy to do in general;
kono
parents:
diff changeset
2146 contains_type_p may return false negatives for non-comparable
kono
parents:
diff changeset
2147 types.
kono
parents:
diff changeset
2148
kono
parents:
diff changeset
2149 If OTR_TYPE is known, we however can expect that
kono
parents:
diff changeset
2150 restrict_to_inner_class should have discovered the same base
kono
parents:
diff changeset
2151 type. */
kono
parents:
diff changeset
2152 if (otr_type && !ctx.maybe_in_construction && !ctx.maybe_derived_type)
kono
parents:
diff changeset
2153 {
kono
parents:
diff changeset
2154 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2155 fprintf (dump_file, "Contextes disagree -> invalid\n");
kono
parents:
diff changeset
2156 goto invalidate;
kono
parents:
diff changeset
2157 }
kono
parents:
diff changeset
2158 }
kono
parents:
diff changeset
2159 /* See if one type contains the other as a field (not base).
kono
parents:
diff changeset
2160 In this case we want to choose the wider type, because it contains
kono
parents:
diff changeset
2161 more information. */
kono
parents:
diff changeset
2162 else if (contains_type_p (ctx.outer_type, ctx.offset - offset,
kono
parents:
diff changeset
2163 outer_type, false, false))
kono
parents:
diff changeset
2164 {
kono
parents:
diff changeset
2165 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2166 fprintf (dump_file, "Second type contain the first as a field\n");
kono
parents:
diff changeset
2167
kono
parents:
diff changeset
2168 if (maybe_derived_type)
kono
parents:
diff changeset
2169 {
kono
parents:
diff changeset
2170 outer_type = ctx.outer_type;
kono
parents:
diff changeset
2171 maybe_derived_type = ctx.maybe_derived_type;
kono
parents:
diff changeset
2172 offset = ctx.offset;
kono
parents:
diff changeset
2173 dynamic = ctx.dynamic;
kono
parents:
diff changeset
2174 updated = true;
kono
parents:
diff changeset
2175 }
kono
parents:
diff changeset
2176
kono
parents:
diff changeset
2177 /* If we do not know how the context is being used, we can
kono
parents:
diff changeset
2178 not clear MAYBE_IN_CONSTRUCTION because it may be offseted
kono
parents:
diff changeset
2179 to other component of OUTER_TYPE later and we know nothing
kono
parents:
diff changeset
2180 about it. */
kono
parents:
diff changeset
2181 if (otr_type && maybe_in_construction
kono
parents:
diff changeset
2182 && !ctx.maybe_in_construction)
kono
parents:
diff changeset
2183 {
kono
parents:
diff changeset
2184 maybe_in_construction = false;
kono
parents:
diff changeset
2185 updated = true;
kono
parents:
diff changeset
2186 }
kono
parents:
diff changeset
2187 }
kono
parents:
diff changeset
2188 else if (contains_type_p (outer_type, offset - ctx.offset,
kono
parents:
diff changeset
2189 ctx.outer_type, false, false))
kono
parents:
diff changeset
2190 {
kono
parents:
diff changeset
2191 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2192 fprintf (dump_file, "First type contain the second as a field\n");
kono
parents:
diff changeset
2193
kono
parents:
diff changeset
2194 if (otr_type && maybe_in_construction
kono
parents:
diff changeset
2195 && !ctx.maybe_in_construction)
kono
parents:
diff changeset
2196 {
kono
parents:
diff changeset
2197 maybe_in_construction = false;
kono
parents:
diff changeset
2198 updated = true;
kono
parents:
diff changeset
2199 }
kono
parents:
diff changeset
2200 }
kono
parents:
diff changeset
2201 /* See if OUTER_TYPE is base of CTX.OUTER_TYPE. */
kono
parents:
diff changeset
2202 else if (contains_type_p (ctx.outer_type,
kono
parents:
diff changeset
2203 ctx.offset - offset, outer_type, false, true))
kono
parents:
diff changeset
2204 {
kono
parents:
diff changeset
2205 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2206 fprintf (dump_file, "First type is base of second\n");
kono
parents:
diff changeset
2207 if (!maybe_derived_type)
kono
parents:
diff changeset
2208 {
kono
parents:
diff changeset
2209 if (!ctx.maybe_in_construction
kono
parents:
diff changeset
2210 && types_odr_comparable (outer_type, ctx.outer_type))
kono
parents:
diff changeset
2211 {
kono
parents:
diff changeset
2212 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2213 fprintf (dump_file, "Second context does not permit base -> invalid\n");
kono
parents:
diff changeset
2214 goto invalidate;
kono
parents:
diff changeset
2215 }
kono
parents:
diff changeset
2216 }
kono
parents:
diff changeset
2217 /* Pick variant deeper in the hiearchy. */
kono
parents:
diff changeset
2218 else
kono
parents:
diff changeset
2219 {
kono
parents:
diff changeset
2220 outer_type = ctx.outer_type;
kono
parents:
diff changeset
2221 maybe_in_construction = ctx.maybe_in_construction;
kono
parents:
diff changeset
2222 maybe_derived_type = ctx.maybe_derived_type;
kono
parents:
diff changeset
2223 offset = ctx.offset;
kono
parents:
diff changeset
2224 dynamic = ctx.dynamic;
kono
parents:
diff changeset
2225 updated = true;
kono
parents:
diff changeset
2226 }
kono
parents:
diff changeset
2227 }
kono
parents:
diff changeset
2228 /* See if CTX.OUTER_TYPE is base of OUTER_TYPE. */
kono
parents:
diff changeset
2229 else if (contains_type_p (outer_type,
kono
parents:
diff changeset
2230 offset - ctx.offset, ctx.outer_type, false, true))
kono
parents:
diff changeset
2231 {
kono
parents:
diff changeset
2232 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2233 fprintf (dump_file, "Second type is base of first\n");
kono
parents:
diff changeset
2234 if (!ctx.maybe_derived_type)
kono
parents:
diff changeset
2235 {
kono
parents:
diff changeset
2236 if (!maybe_in_construction
kono
parents:
diff changeset
2237 && types_odr_comparable (outer_type, ctx.outer_type))
kono
parents:
diff changeset
2238 {
kono
parents:
diff changeset
2239 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2240 fprintf (dump_file, "First context does not permit base -> invalid\n");
kono
parents:
diff changeset
2241 goto invalidate;
kono
parents:
diff changeset
2242 }
kono
parents:
diff changeset
2243 /* Pick the base type. */
kono
parents:
diff changeset
2244 else if (maybe_in_construction)
kono
parents:
diff changeset
2245 {
kono
parents:
diff changeset
2246 outer_type = ctx.outer_type;
kono
parents:
diff changeset
2247 maybe_in_construction = ctx.maybe_in_construction;
kono
parents:
diff changeset
2248 maybe_derived_type = ctx.maybe_derived_type;
kono
parents:
diff changeset
2249 offset = ctx.offset;
kono
parents:
diff changeset
2250 dynamic = ctx.dynamic;
kono
parents:
diff changeset
2251 updated = true;
kono
parents:
diff changeset
2252 }
kono
parents:
diff changeset
2253 }
kono
parents:
diff changeset
2254 }
kono
parents:
diff changeset
2255 /* TODO handle merging using hiearchy. */
kono
parents:
diff changeset
2256 else if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2257 fprintf (dump_file, "Giving up on merge\n");
kono
parents:
diff changeset
2258
kono
parents:
diff changeset
2259 updated |= combine_speculation_with (ctx.speculative_outer_type,
kono
parents:
diff changeset
2260 ctx.speculative_offset,
kono
parents:
diff changeset
2261 ctx.speculative_maybe_derived_type,
kono
parents:
diff changeset
2262 otr_type);
kono
parents:
diff changeset
2263
kono
parents:
diff changeset
2264 if (updated && dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2265 {
kono
parents:
diff changeset
2266 fprintf (dump_file, "Updated as: ");
kono
parents:
diff changeset
2267 dump (dump_file);
kono
parents:
diff changeset
2268 fprintf (dump_file, "\n");
kono
parents:
diff changeset
2269 }
kono
parents:
diff changeset
2270 return updated;
kono
parents:
diff changeset
2271
kono
parents:
diff changeset
2272 invalidate:
kono
parents:
diff changeset
2273 invalid = true;
kono
parents:
diff changeset
2274 clear_speculation ();
kono
parents:
diff changeset
2275 clear_outer_type ();
kono
parents:
diff changeset
2276 return true;
kono
parents:
diff changeset
2277 }
kono
parents:
diff changeset
2278
kono
parents:
diff changeset
2279 /* Take non-speculative info, merge it with speculative and clear speculation.
kono
parents:
diff changeset
2280 Used when we no longer manage to keep track of actual outer type, but we
kono
parents:
diff changeset
2281 think it is still there.
kono
parents:
diff changeset
2282
kono
parents:
diff changeset
2283 If OTR_TYPE is set, the transformation can be done more effectively assuming
kono
parents:
diff changeset
2284 that context is going to be used only that way. */
kono
parents:
diff changeset
2285
kono
parents:
diff changeset
2286 void
kono
parents:
diff changeset
2287 ipa_polymorphic_call_context::make_speculative (tree otr_type)
kono
parents:
diff changeset
2288 {
kono
parents:
diff changeset
2289 tree spec_outer_type = outer_type;
kono
parents:
diff changeset
2290 HOST_WIDE_INT spec_offset = offset;
kono
parents:
diff changeset
2291 bool spec_maybe_derived_type = maybe_derived_type;
kono
parents:
diff changeset
2292
kono
parents:
diff changeset
2293 if (invalid)
kono
parents:
diff changeset
2294 {
kono
parents:
diff changeset
2295 invalid = false;
kono
parents:
diff changeset
2296 clear_outer_type ();
kono
parents:
diff changeset
2297 clear_speculation ();
kono
parents:
diff changeset
2298 return;
kono
parents:
diff changeset
2299 }
kono
parents:
diff changeset
2300 if (!outer_type)
kono
parents:
diff changeset
2301 return;
kono
parents:
diff changeset
2302 clear_outer_type ();
kono
parents:
diff changeset
2303 combine_speculation_with (spec_outer_type, spec_offset,
kono
parents:
diff changeset
2304 spec_maybe_derived_type,
kono
parents:
diff changeset
2305 otr_type);
kono
parents:
diff changeset
2306 }
kono
parents:
diff changeset
2307
kono
parents:
diff changeset
2308 /* Use when we can not track dynamic type change. This speculatively assume
kono
parents:
diff changeset
2309 type change is not happening. */
kono
parents:
diff changeset
2310
kono
parents:
diff changeset
2311 void
kono
parents:
diff changeset
2312 ipa_polymorphic_call_context::possible_dynamic_type_change (bool in_poly_cdtor,
kono
parents:
diff changeset
2313 tree otr_type)
kono
parents:
diff changeset
2314 {
kono
parents:
diff changeset
2315 if (dynamic)
kono
parents:
diff changeset
2316 make_speculative (otr_type);
kono
parents:
diff changeset
2317 else if (in_poly_cdtor)
kono
parents:
diff changeset
2318 maybe_in_construction = true;
kono
parents:
diff changeset
2319 }
kono
parents:
diff changeset
2320
kono
parents:
diff changeset
2321 /* Return TRUE if this context conveys the same information as OTHER. */
kono
parents:
diff changeset
2322
kono
parents:
diff changeset
2323 bool
kono
parents:
diff changeset
2324 ipa_polymorphic_call_context::equal_to
kono
parents:
diff changeset
2325 (const ipa_polymorphic_call_context &x) const
kono
parents:
diff changeset
2326 {
kono
parents:
diff changeset
2327 if (useless_p ())
kono
parents:
diff changeset
2328 return x.useless_p ();
kono
parents:
diff changeset
2329 if (invalid)
kono
parents:
diff changeset
2330 return x.invalid;
kono
parents:
diff changeset
2331 if (x.useless_p () || x.invalid)
kono
parents:
diff changeset
2332 return false;
kono
parents:
diff changeset
2333
kono
parents:
diff changeset
2334 if (outer_type)
kono
parents:
diff changeset
2335 {
kono
parents:
diff changeset
2336 if (!x.outer_type
kono
parents:
diff changeset
2337 || !types_odr_comparable (outer_type, x.outer_type)
kono
parents:
diff changeset
2338 || !types_same_for_odr (outer_type, x.outer_type)
kono
parents:
diff changeset
2339 || offset != x.offset
kono
parents:
diff changeset
2340 || maybe_in_construction != x.maybe_in_construction
kono
parents:
diff changeset
2341 || maybe_derived_type != x.maybe_derived_type
kono
parents:
diff changeset
2342 || dynamic != x.dynamic)
kono
parents:
diff changeset
2343 return false;
kono
parents:
diff changeset
2344 }
kono
parents:
diff changeset
2345 else if (x.outer_type)
kono
parents:
diff changeset
2346 return false;
kono
parents:
diff changeset
2347
kono
parents:
diff changeset
2348
kono
parents:
diff changeset
2349 if (speculative_outer_type
kono
parents:
diff changeset
2350 && speculation_consistent_p (speculative_outer_type, speculative_offset,
kono
parents:
diff changeset
2351 speculative_maybe_derived_type, NULL_TREE))
kono
parents:
diff changeset
2352 {
kono
parents:
diff changeset
2353 if (!x.speculative_outer_type)
kono
parents:
diff changeset
2354 return false;
kono
parents:
diff changeset
2355
kono
parents:
diff changeset
2356 if (!types_odr_comparable (speculative_outer_type,
kono
parents:
diff changeset
2357 x.speculative_outer_type)
kono
parents:
diff changeset
2358 || !types_same_for_odr (speculative_outer_type,
kono
parents:
diff changeset
2359 x.speculative_outer_type)
kono
parents:
diff changeset
2360 || speculative_offset != x.speculative_offset
kono
parents:
diff changeset
2361 || speculative_maybe_derived_type != x.speculative_maybe_derived_type)
kono
parents:
diff changeset
2362 return false;
kono
parents:
diff changeset
2363 }
kono
parents:
diff changeset
2364 else if (x.speculative_outer_type
kono
parents:
diff changeset
2365 && x.speculation_consistent_p (x.speculative_outer_type,
kono
parents:
diff changeset
2366 x.speculative_offset,
kono
parents:
diff changeset
2367 x.speculative_maybe_derived_type,
kono
parents:
diff changeset
2368 NULL))
kono
parents:
diff changeset
2369 return false;
kono
parents:
diff changeset
2370
kono
parents:
diff changeset
2371 return true;
kono
parents:
diff changeset
2372 }
kono
parents:
diff changeset
2373
kono
parents:
diff changeset
2374 /* Modify context to be strictly less restrictive than CTX. */
kono
parents:
diff changeset
2375
kono
parents:
diff changeset
2376 bool
kono
parents:
diff changeset
2377 ipa_polymorphic_call_context::meet_with (ipa_polymorphic_call_context ctx,
kono
parents:
diff changeset
2378 tree otr_type)
kono
parents:
diff changeset
2379 {
kono
parents:
diff changeset
2380 bool updated = false;
kono
parents:
diff changeset
2381
kono
parents:
diff changeset
2382 if (useless_p () || ctx.invalid)
kono
parents:
diff changeset
2383 return false;
kono
parents:
diff changeset
2384
kono
parents:
diff changeset
2385 /* Restricting context to inner type makes merging easier, however do not
kono
parents:
diff changeset
2386 do that unless we know how the context is used (OTR_TYPE is non-NULL) */
kono
parents:
diff changeset
2387 if (otr_type && !useless_p () && !ctx.useless_p ())
kono
parents:
diff changeset
2388 {
kono
parents:
diff changeset
2389 restrict_to_inner_class (otr_type);
kono
parents:
diff changeset
2390 ctx.restrict_to_inner_class (otr_type);
kono
parents:
diff changeset
2391 if(invalid)
kono
parents:
diff changeset
2392 return false;
kono
parents:
diff changeset
2393 }
kono
parents:
diff changeset
2394
kono
parents:
diff changeset
2395 if (equal_to (ctx))
kono
parents:
diff changeset
2396 return false;
kono
parents:
diff changeset
2397
kono
parents:
diff changeset
2398 if (ctx.useless_p () || invalid)
kono
parents:
diff changeset
2399 {
kono
parents:
diff changeset
2400 *this = ctx;
kono
parents:
diff changeset
2401 return true;
kono
parents:
diff changeset
2402 }
kono
parents:
diff changeset
2403
kono
parents:
diff changeset
2404 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2405 {
kono
parents:
diff changeset
2406 fprintf (dump_file, "Polymorphic call context meet:");
kono
parents:
diff changeset
2407 dump (dump_file);
kono
parents:
diff changeset
2408 fprintf (dump_file, "With context: ");
kono
parents:
diff changeset
2409 ctx.dump (dump_file);
kono
parents:
diff changeset
2410 if (otr_type)
kono
parents:
diff changeset
2411 {
kono
parents:
diff changeset
2412 fprintf (dump_file, "To be used with type: ");
kono
parents:
diff changeset
2413 print_generic_expr (dump_file, otr_type, TDF_SLIM);
kono
parents:
diff changeset
2414 fprintf (dump_file, "\n");
kono
parents:
diff changeset
2415 }
kono
parents:
diff changeset
2416 }
kono
parents:
diff changeset
2417
kono
parents:
diff changeset
2418 if (!dynamic && ctx.dynamic)
kono
parents:
diff changeset
2419 {
kono
parents:
diff changeset
2420 dynamic = true;
kono
parents:
diff changeset
2421 updated = true;
kono
parents:
diff changeset
2422 }
kono
parents:
diff changeset
2423
kono
parents:
diff changeset
2424 /* If call is known to be invalid, we are done. */
kono
parents:
diff changeset
2425 if (!outer_type)
kono
parents:
diff changeset
2426 ;
kono
parents:
diff changeset
2427 else if (!ctx.outer_type)
kono
parents:
diff changeset
2428 {
kono
parents:
diff changeset
2429 clear_outer_type ();
kono
parents:
diff changeset
2430 updated = true;
kono
parents:
diff changeset
2431 }
kono
parents:
diff changeset
2432 /* If types are known to be same, merging is quite easy. */
kono
parents:
diff changeset
2433 else if (types_must_be_same_for_odr (outer_type, ctx.outer_type))
kono
parents:
diff changeset
2434 {
kono
parents:
diff changeset
2435 if (offset != ctx.offset
kono
parents:
diff changeset
2436 && TYPE_SIZE (outer_type)
kono
parents:
diff changeset
2437 && TREE_CODE (TYPE_SIZE (outer_type)) == INTEGER_CST)
kono
parents:
diff changeset
2438 {
kono
parents:
diff changeset
2439 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2440 fprintf (dump_file, "Outer types match, offset mismatch -> clearing\n");
kono
parents:
diff changeset
2441 clear_outer_type ();
kono
parents:
diff changeset
2442 return true;
kono
parents:
diff changeset
2443 }
kono
parents:
diff changeset
2444 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2445 fprintf (dump_file, "Outer types match, merging flags\n");
kono
parents:
diff changeset
2446 if (!maybe_in_construction && ctx.maybe_in_construction)
kono
parents:
diff changeset
2447 {
kono
parents:
diff changeset
2448 updated = true;
kono
parents:
diff changeset
2449 maybe_in_construction = true;
kono
parents:
diff changeset
2450 }
kono
parents:
diff changeset
2451 if (!maybe_derived_type && ctx.maybe_derived_type)
kono
parents:
diff changeset
2452 {
kono
parents:
diff changeset
2453 updated = true;
kono
parents:
diff changeset
2454 maybe_derived_type = true;
kono
parents:
diff changeset
2455 }
kono
parents:
diff changeset
2456 if (!dynamic && ctx.dynamic)
kono
parents:
diff changeset
2457 {
kono
parents:
diff changeset
2458 updated = true;
kono
parents:
diff changeset
2459 dynamic = true;
kono
parents:
diff changeset
2460 }
kono
parents:
diff changeset
2461 }
kono
parents:
diff changeset
2462 /* See if one type contains the other as a field (not base). */
kono
parents:
diff changeset
2463 else if (contains_type_p (ctx.outer_type, ctx.offset - offset,
kono
parents:
diff changeset
2464 outer_type, false, false))
kono
parents:
diff changeset
2465 {
kono
parents:
diff changeset
2466 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2467 fprintf (dump_file, "Second type contain the first as a field\n");
kono
parents:
diff changeset
2468
kono
parents:
diff changeset
2469 /* The second type is more specified, so we keep the first.
kono
parents:
diff changeset
2470 We need to set DYNAMIC flag to avoid declaring context INVALID
kono
parents:
diff changeset
2471 of OFFSET ends up being out of range. */
kono
parents:
diff changeset
2472 if (!dynamic
kono
parents:
diff changeset
2473 && (ctx.dynamic
kono
parents:
diff changeset
2474 || (!otr_type
kono
parents:
diff changeset
2475 && (!TYPE_SIZE (ctx.outer_type)
kono
parents:
diff changeset
2476 || !TYPE_SIZE (outer_type)
kono
parents:
diff changeset
2477 || !operand_equal_p (TYPE_SIZE (ctx.outer_type),
kono
parents:
diff changeset
2478 TYPE_SIZE (outer_type), 0)))))
kono
parents:
diff changeset
2479 {
kono
parents:
diff changeset
2480 dynamic = true;
kono
parents:
diff changeset
2481 updated = true;
kono
parents:
diff changeset
2482 }
kono
parents:
diff changeset
2483 }
kono
parents:
diff changeset
2484 else if (contains_type_p (outer_type, offset - ctx.offset,
kono
parents:
diff changeset
2485 ctx.outer_type, false, false))
kono
parents:
diff changeset
2486 {
kono
parents:
diff changeset
2487 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2488 fprintf (dump_file, "First type contain the second as a field\n");
kono
parents:
diff changeset
2489
kono
parents:
diff changeset
2490 if (!dynamic
kono
parents:
diff changeset
2491 && (ctx.dynamic
kono
parents:
diff changeset
2492 || (!otr_type
kono
parents:
diff changeset
2493 && (!TYPE_SIZE (ctx.outer_type)
kono
parents:
diff changeset
2494 || !TYPE_SIZE (outer_type)
kono
parents:
diff changeset
2495 || !operand_equal_p (TYPE_SIZE (ctx.outer_type),
kono
parents:
diff changeset
2496 TYPE_SIZE (outer_type), 0)))))
kono
parents:
diff changeset
2497 dynamic = true;
kono
parents:
diff changeset
2498 outer_type = ctx.outer_type;
kono
parents:
diff changeset
2499 offset = ctx.offset;
kono
parents:
diff changeset
2500 dynamic = ctx.dynamic;
kono
parents:
diff changeset
2501 maybe_in_construction = ctx.maybe_in_construction;
kono
parents:
diff changeset
2502 maybe_derived_type = ctx.maybe_derived_type;
kono
parents:
diff changeset
2503 updated = true;
kono
parents:
diff changeset
2504 }
kono
parents:
diff changeset
2505 /* See if OUTER_TYPE is base of CTX.OUTER_TYPE. */
kono
parents:
diff changeset
2506 else if (contains_type_p (ctx.outer_type,
kono
parents:
diff changeset
2507 ctx.offset - offset, outer_type, false, true))
kono
parents:
diff changeset
2508 {
kono
parents:
diff changeset
2509 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2510 fprintf (dump_file, "First type is base of second\n");
kono
parents:
diff changeset
2511 if (!maybe_derived_type)
kono
parents:
diff changeset
2512 {
kono
parents:
diff changeset
2513 maybe_derived_type = true;
kono
parents:
diff changeset
2514 updated = true;
kono
parents:
diff changeset
2515 }
kono
parents:
diff changeset
2516 if (!maybe_in_construction && ctx.maybe_in_construction)
kono
parents:
diff changeset
2517 {
kono
parents:
diff changeset
2518 maybe_in_construction = true;
kono
parents:
diff changeset
2519 updated = true;
kono
parents:
diff changeset
2520 }
kono
parents:
diff changeset
2521 if (!dynamic && ctx.dynamic)
kono
parents:
diff changeset
2522 {
kono
parents:
diff changeset
2523 dynamic = true;
kono
parents:
diff changeset
2524 updated = true;
kono
parents:
diff changeset
2525 }
kono
parents:
diff changeset
2526 }
kono
parents:
diff changeset
2527 /* See if CTX.OUTER_TYPE is base of OUTER_TYPE. */
kono
parents:
diff changeset
2528 else if (contains_type_p (outer_type,
kono
parents:
diff changeset
2529 offset - ctx.offset, ctx.outer_type, false, true))
kono
parents:
diff changeset
2530 {
kono
parents:
diff changeset
2531 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2532 fprintf (dump_file, "Second type is base of first\n");
kono
parents:
diff changeset
2533 outer_type = ctx.outer_type;
kono
parents:
diff changeset
2534 offset = ctx.offset;
kono
parents:
diff changeset
2535 updated = true;
kono
parents:
diff changeset
2536 if (!maybe_derived_type)
kono
parents:
diff changeset
2537 maybe_derived_type = true;
kono
parents:
diff changeset
2538 if (!maybe_in_construction && ctx.maybe_in_construction)
kono
parents:
diff changeset
2539 maybe_in_construction = true;
kono
parents:
diff changeset
2540 if (!dynamic && ctx.dynamic)
kono
parents:
diff changeset
2541 dynamic = true;
kono
parents:
diff changeset
2542 }
kono
parents:
diff changeset
2543 /* TODO handle merging using hiearchy. */
kono
parents:
diff changeset
2544 else
kono
parents:
diff changeset
2545 {
kono
parents:
diff changeset
2546 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2547 fprintf (dump_file, "Giving up on meet\n");
kono
parents:
diff changeset
2548 clear_outer_type ();
kono
parents:
diff changeset
2549 updated = true;
kono
parents:
diff changeset
2550 }
kono
parents:
diff changeset
2551
kono
parents:
diff changeset
2552 updated |= meet_speculation_with (ctx.speculative_outer_type,
kono
parents:
diff changeset
2553 ctx.speculative_offset,
kono
parents:
diff changeset
2554 ctx.speculative_maybe_derived_type,
kono
parents:
diff changeset
2555 otr_type);
kono
parents:
diff changeset
2556
kono
parents:
diff changeset
2557 if (updated && dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2558 {
kono
parents:
diff changeset
2559 fprintf (dump_file, "Updated as: ");
kono
parents:
diff changeset
2560 dump (dump_file);
kono
parents:
diff changeset
2561 fprintf (dump_file, "\n");
kono
parents:
diff changeset
2562 }
kono
parents:
diff changeset
2563 return updated;
kono
parents:
diff changeset
2564 }